bitkeeper revision 1.1010.1.9 (40dc4078vvvprFxMFMTOULzuaeEQoQ)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Fri, 25 Jun 2004 15:10:48 +0000 (15:10 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Fri, 25 Jun 2004 15:10:48 +0000 (15:10 +0000)
Renaming 'xenmgr' to 'xen.xend'.

139 files changed:
.rootkeys
extras/mini-os/h/hypervisor.h
linux-2.4.26-xen-sparse/mkbuildtree
tools/Makefile
tools/misc/Makefile
tools/xc/lib/Makefile
tools/xc/py/Xc.c
tools/xc/py/setup.py
tools/xen/Makefile [new file with mode: 0644]
tools/xen/lib/__init__.py [new file with mode: 0644]
tools/xen/lib/xend/Args.py [new file with mode: 0644]
tools/xen/lib/xend/EventServer.py [new file with mode: 0644]
tools/xen/lib/xend/EventTypes.py [new file with mode: 0644]
tools/xen/lib/xend/PrettyPrint.py [new file with mode: 0644]
tools/xen/lib/xend/XendBridge.py [new file with mode: 0644]
tools/xen/lib/xend/XendClient.py [new file with mode: 0644]
tools/xen/lib/xend/XendConsole.py [new file with mode: 0644]
tools/xen/lib/xend/XendDB.py [new file with mode: 0644]
tools/xen/lib/xend/XendDomain.py [new file with mode: 0644]
tools/xen/lib/xend/XendDomainConfig.py [new file with mode: 0644]
tools/xen/lib/xend/XendDomainInfo.py [new file with mode: 0644]
tools/xen/lib/xend/XendMigrate.py [new file with mode: 0644]
tools/xen/lib/xend/XendNode.py [new file with mode: 0644]
tools/xen/lib/xend/XendRoot.py [new file with mode: 0644]
tools/xen/lib/xend/XendVnet.py [new file with mode: 0644]
tools/xen/lib/xend/__init__.py [new file with mode: 0644]
tools/xen/lib/xend/encode.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvBase.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvConsole.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvConsoleDir.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvDaemon.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvDeviceDir.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvDir.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvDomain.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvDomainDir.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvEventDir.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvNode.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvRoot.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvServer.py [new file with mode: 0644]
tools/xen/lib/xend/server/SrvVnetDir.py [new file with mode: 0644]
tools/xen/lib/xend/server/__init__.py [new file with mode: 0644]
tools/xen/lib/xend/server/blkif.py [new file with mode: 0755]
tools/xen/lib/xend/server/channel.py [new file with mode: 0755]
tools/xen/lib/xend/server/console.py [new file with mode: 0755]
tools/xen/lib/xend/server/controller.py [new file with mode: 0755]
tools/xen/lib/xend/server/cstruct.py [new file with mode: 0755]
tools/xen/lib/xend/server/domain.py [new file with mode: 0644]
tools/xen/lib/xend/server/messages.py [new file with mode: 0644]
tools/xen/lib/xend/server/netif.py [new file with mode: 0755]
tools/xen/lib/xend/server/params.py [new file with mode: 0644]
tools/xen/lib/xend/sxp.py [new file with mode: 0644]
tools/xen/lib/xm/__init__.py [new file with mode: 0644]
tools/xen/lib/xm/create.py [new file with mode: 0644]
tools/xen/lib/xm/main.py [new file with mode: 0644]
tools/xen/lib/xm/opts.py [new file with mode: 0644]
tools/xen/lib/xm/shutdown.py [new file with mode: 0644]
tools/xen/netfix [new file with mode: 0644]
tools/xen/setup.py [new file with mode: 0644]
tools/xen/xend [new file with mode: 0644]
tools/xen/xm [new file with mode: 0755]
tools/xend-old/Makefile [new file with mode: 0644]
tools/xend-old/lib/__init__.py [new file with mode: 0644]
tools/xend-old/lib/blkif.py [new file with mode: 0644]
tools/xend-old/lib/console.py [new file with mode: 0644]
tools/xend-old/lib/domain_controller.h [new file with mode: 0644]
tools/xend-old/lib/main.py [new file with mode: 0755]
tools/xend-old/lib/manager.py [new file with mode: 0644]
tools/xend-old/lib/netif.py [new file with mode: 0644]
tools/xend-old/lib/utils.c [new file with mode: 0644]
tools/xend-old/setup.py [new file with mode: 0644]
tools/xend-old/xend [new file with mode: 0755]
tools/xend/Makefile [deleted file]
tools/xend/lib/__init__.py [deleted file]
tools/xend/lib/blkif.py [deleted file]
tools/xend/lib/console.py [deleted file]
tools/xend/lib/domain_controller.h [deleted file]
tools/xend/lib/main.py [deleted file]
tools/xend/lib/manager.py [deleted file]
tools/xend/lib/netif.py [deleted file]
tools/xend/lib/utils.c [deleted file]
tools/xend/setup.py [deleted file]
tools/xend/xend [deleted file]
tools/xenmgr/Makefile [deleted file]
tools/xenmgr/lib/Args.py [deleted file]
tools/xenmgr/lib/EventServer.py [deleted file]
tools/xenmgr/lib/EventTypes.py [deleted file]
tools/xenmgr/lib/PrettyPrint.py [deleted file]
tools/xenmgr/lib/XendBridge.py [deleted file]
tools/xenmgr/lib/XendClient.py [deleted file]
tools/xenmgr/lib/XendConsole.py [deleted file]
tools/xenmgr/lib/XendDB.py [deleted file]
tools/xenmgr/lib/XendDomain.py [deleted file]
tools/xenmgr/lib/XendDomainConfig.py [deleted file]
tools/xenmgr/lib/XendDomainInfo.py [deleted file]
tools/xenmgr/lib/XendMigrate.py [deleted file]
tools/xenmgr/lib/XendNode.py [deleted file]
tools/xenmgr/lib/XendRoot.py [deleted file]
tools/xenmgr/lib/XendVnet.py [deleted file]
tools/xenmgr/lib/__init__.py [deleted file]
tools/xenmgr/lib/encode.py [deleted file]
tools/xenmgr/lib/server/SrvBase.py [deleted file]
tools/xenmgr/lib/server/SrvConsole.py [deleted file]
tools/xenmgr/lib/server/SrvConsoleDir.py [deleted file]
tools/xenmgr/lib/server/SrvConsoleServer.py [deleted file]
tools/xenmgr/lib/server/SrvDeviceDir.py [deleted file]
tools/xenmgr/lib/server/SrvDir.py [deleted file]
tools/xenmgr/lib/server/SrvDomain.py [deleted file]
tools/xenmgr/lib/server/SrvDomainDir.py [deleted file]
tools/xenmgr/lib/server/SrvEventDir.py [deleted file]
tools/xenmgr/lib/server/SrvNode.py [deleted file]
tools/xenmgr/lib/server/SrvRoot.py [deleted file]
tools/xenmgr/lib/server/SrvServer.py [deleted file]
tools/xenmgr/lib/server/SrvVnetDir.py [deleted file]
tools/xenmgr/lib/server/__init__.py [deleted file]
tools/xenmgr/lib/server/blkif.py [deleted file]
tools/xenmgr/lib/server/channel.py [deleted file]
tools/xenmgr/lib/server/console.py [deleted file]
tools/xenmgr/lib/server/controller.py [deleted file]
tools/xenmgr/lib/server/cstruct.py [deleted file]
tools/xenmgr/lib/server/domain.py [deleted file]
tools/xenmgr/lib/server/messages.py [deleted file]
tools/xenmgr/lib/server/netif.py [deleted file]
tools/xenmgr/lib/server/params.py [deleted file]
tools/xenmgr/lib/sxp.py [deleted file]
tools/xenmgr/lib/xm/__init__.py [deleted file]
tools/xenmgr/lib/xm/create.py [deleted file]
tools/xenmgr/lib/xm/main.py [deleted file]
tools/xenmgr/lib/xm/opts.py [deleted file]
tools/xenmgr/lib/xm/shutdown.py [deleted file]
tools/xenmgr/netfix [deleted file]
tools/xenmgr/setup.py [deleted file]
tools/xenmgr/xend [deleted file]
tools/xenmgr/xenmgrd [deleted file]
tools/xenmgr/xm [deleted file]
tools/xentrace/Makefile
tools/xu/lib/__init__.py [new file with mode: 0644]
tools/xu/lib/domain_controller.h [new file with mode: 0644]
tools/xu/lib/xu.c [new file with mode: 0644]
tools/xu/setup.py [new file with mode: 0644]

index 2e382934edc732ace4b7c431e98558fe0b585bff..1aabafc723b37900bf9e1065c2068097f8b01470 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3fbd0a3dTwnDcfdw0-v46dPbX98zDw tools/xc/py/Makefile
 3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/xc/py/Xc.c
 3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py
+40c9c468icGyC5RAF1bRKsCXPDCvsA tools/xen/Makefile
+40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/xen/lib/__init__.py
+40c9c468SNuObE_YWARyS0hzTPSzKg tools/xen/lib/xend/Args.py
+40c9c468Um_qc66OQeLEceIz1pgD5g tools/xen/lib/xend/EventServer.py
+40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xen/lib/xend/EventTypes.py
+40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/xen/lib/xend/PrettyPrint.py
+40d8915cyoVA0hJxiBFNymL7YvDaRg tools/xen/lib/xend/XendBridge.py
+40c9c4688m3eqnC8fhLu1APm36VOVA tools/xen/lib/xend/XendClient.py
+40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/xen/lib/xend/XendConsole.py
+40c9c468WnXs6eOUSff23IIGI4kMfQ tools/xen/lib/xend/XendDB.py
+40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/xen/lib/xend/XendDomain.py
+40c9c468bbKq3uC7_fuNUkiMMjArdw tools/xen/lib/xend/XendDomainConfig.py
+40c9c4685ykq87_n1kVUbMr9flx9fg tools/xen/lib/xend/XendDomainInfo.py
+40c9c46854nsHmuxHQHncKk5rAs5NA tools/xen/lib/xend/XendMigrate.py
+40c9c468M96gA1EYDvNa5w5kQNYLFA tools/xen/lib/xend/XendNode.py
+40c9c4686jruMyZIqiaZRMiMoqMJtg tools/xen/lib/xend/XendRoot.py
+40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/xen/lib/xend/XendVnet.py
+40c9c468x191zetrVlMnExfsQWHxIQ tools/xen/lib/xend/__init__.py
+40c9c468S2YnCEKmk4ey8XQIST7INg tools/xen/lib/xend/encode.py
+40c9c468DCpMe542varOolW1Xc68ew tools/xen/lib/xend/server/SrvBase.py
+40c9c468IxQabrKJSWs0aEjl-27mRQ tools/xen/lib/xend/server/SrvConsole.py
+40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/xen/lib/xend/server/SrvConsoleDir.py
+40c9c468woSmBByfeXA4o_jGf2gCgA tools/xen/lib/xend/server/SrvDaemon.py
+40c9c468kACsmkqjxBWKHRo071L26w tools/xen/lib/xend/server/SrvDeviceDir.py
+40c9c468EQZJVkCLds-OhesJVVyZbQ tools/xen/lib/xend/server/SrvDir.py
+40c9c468TyHZUq8sk0FF_vxM6Sozrg tools/xen/lib/xend/server/SrvDomain.py
+40c9c469WzajDjutou3X7FmL9hMf3g tools/xen/lib/xend/server/SrvDomainDir.py
+40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/xen/lib/xend/server/SrvEventDir.py
+40c9c4694eu5759Dehr4Uhakei0EMg tools/xen/lib/xend/server/SrvNode.py
+40c9c469TaZ83ypsrktmPSHLEZiP5w tools/xen/lib/xend/server/SrvRoot.py
+40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/xen/lib/xend/server/SrvServer.py
+40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/xen/lib/xend/server/SrvVnetDir.py
+40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/xen/lib/xend/server/__init__.py
+40c9c4692hckPol_EK0EGB16ZyDsyQ tools/xen/lib/xend/server/blkif.py
+40c9c469N2-b3GqpLHHHPZykJPLVvA tools/xen/lib/xend/server/channel.py
+40c9c469hJ_IlatRne-9QEa0-wlquw tools/xen/lib/xend/server/console.py
+40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/xen/lib/xend/server/controller.py
+40c9c469vHh-qLiiubdbKEQbJf18Zw tools/xen/lib/xend/server/cstruct.py
+40d83983OXjt-y3HjSCcuoPp9rzvmw tools/xen/lib/xend/server/domain.py
+40c9c469yrm31i60pGKslTi2Zgpotg tools/xen/lib/xend/server/messages.py
+40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/xen/lib/xend/server/netif.py
+40c9c469ZqILEQ8x6yWy0_51jopiCg tools/xen/lib/xend/server/params.py
+40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/xen/lib/xend/sxp.py
+40d05079aFRp6NQdo5wIh5Ly31c0cg tools/xen/lib/xm/__init__.py
+40cf2937gKQcATgXKGtNeWb1PDH5nA tools/xen/lib/xm/create.py
+40cf2937isyS250zyd0Q2GuEDoNXfQ tools/xen/lib/xm/main.py
+40cf2937PSslwBliN1g7ofDy2H_RhA tools/xen/lib/xm/opts.py
+40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/xen/lib/xm/shutdown.py
+40c9c469kT0H9COWzA4XzPBjWK0WsA tools/xen/netfix
+40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/xen/setup.py
+40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/xen/xend
+40cf2937dqM1jWW87O5OoOYND8leuA tools/xen/xm
 4055ee41IfFazrwadCH2J72nz-A9YA tools/xenctl/Makefile
 4055ee4b_4Rvns_KzE12csI14EKK6Q tools/xenctl/lib/__init__.py
 4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xenctl/lib/console_client.py
 4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xenctl/lib/tempfile.py
 3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xenctl/lib/utils.py
 4055ee44Bu6oP7U0WxxXypbUt4dNPQ tools/xenctl/setup.py
-40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend/Makefile
-4055ad95Se-FqttgxollqOAAHB94zA tools/xend/lib/__init__.py
-4092738fMRGC9fFBcPRCWaJaj9U3ag tools/xend/lib/blkif.py
-4055ad97wMLUj0BZT0e_T0EwQN0Bvw tools/xend/lib/console.py
-4048c0ddsF0WrU7HUzTvg1MJoCIfWg tools/xend/lib/domain_controller.h
-4054a301VEag2GwrBrFBna5U1BGlLA tools/xend/lib/main.py
-4055ad9ah9IuC3sJT2c_gYIFY5Tw_g tools/xend/lib/manager.py
-409ba2e729HhE7fEra4B5EqX-F8Xzw tools/xend/lib/netif.py
-40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend/lib/utils.c
-4054a2fdkdATEnRw-U7AUlgu-6JiUA tools/xend/setup.py
-4056cd26Qyp09iNoOjrvzg8KYzSqOw tools/xend/xend
-40c9c468icGyC5RAF1bRKsCXPDCvsA tools/xenmgr/Makefile
-40c9c468SNuObE_YWARyS0hzTPSzKg tools/xenmgr/lib/Args.py
-40c9c468Um_qc66OQeLEceIz1pgD5g tools/xenmgr/lib/EventServer.py
-40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xenmgr/lib/EventTypes.py
-40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/xenmgr/lib/PrettyPrint.py
-40d8915cyoVA0hJxiBFNymL7YvDaRg tools/xenmgr/lib/XendBridge.py
-40c9c4688m3eqnC8fhLu1APm36VOVA tools/xenmgr/lib/XendClient.py
-40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/xenmgr/lib/XendConsole.py
-40c9c468WnXs6eOUSff23IIGI4kMfQ tools/xenmgr/lib/XendDB.py
-40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/xenmgr/lib/XendDomain.py
-40c9c468bbKq3uC7_fuNUkiMMjArdw tools/xenmgr/lib/XendDomainConfig.py
-40c9c4685ykq87_n1kVUbMr9flx9fg tools/xenmgr/lib/XendDomainInfo.py
-40c9c46854nsHmuxHQHncKk5rAs5NA tools/xenmgr/lib/XendMigrate.py
-40c9c468M96gA1EYDvNa5w5kQNYLFA tools/xenmgr/lib/XendNode.py
-40c9c4686jruMyZIqiaZRMiMoqMJtg tools/xenmgr/lib/XendRoot.py
-40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/xenmgr/lib/XendVnet.py
-40c9c468x191zetrVlMnExfsQWHxIQ tools/xenmgr/lib/__init__.py
-40c9c468S2YnCEKmk4ey8XQIST7INg tools/xenmgr/lib/encode.py
-40c9c468DCpMe542varOolW1Xc68ew tools/xenmgr/lib/server/SrvBase.py
-40c9c468IxQabrKJSWs0aEjl-27mRQ tools/xenmgr/lib/server/SrvConsole.py
-40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/xenmgr/lib/server/SrvConsoleDir.py
-40c9c468woSmBByfeXA4o_jGf2gCgA tools/xenmgr/lib/server/SrvConsoleServer.py
-40c9c468kACsmkqjxBWKHRo071L26w tools/xenmgr/lib/server/SrvDeviceDir.py
-40c9c468EQZJVkCLds-OhesJVVyZbQ tools/xenmgr/lib/server/SrvDir.py
-40c9c468TyHZUq8sk0FF_vxM6Sozrg tools/xenmgr/lib/server/SrvDomain.py
-40c9c469WzajDjutou3X7FmL9hMf3g tools/xenmgr/lib/server/SrvDomainDir.py
-40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/xenmgr/lib/server/SrvEventDir.py
-40c9c4694eu5759Dehr4Uhakei0EMg tools/xenmgr/lib/server/SrvNode.py
-40c9c469TaZ83ypsrktmPSHLEZiP5w tools/xenmgr/lib/server/SrvRoot.py
-40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/xenmgr/lib/server/SrvServer.py
-40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/xenmgr/lib/server/SrvVnetDir.py
-40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/xenmgr/lib/server/__init__.py
-40c9c4692hckPol_EK0EGB16ZyDsyQ tools/xenmgr/lib/server/blkif.py
-40c9c469N2-b3GqpLHHHPZykJPLVvA tools/xenmgr/lib/server/channel.py
-40c9c469hJ_IlatRne-9QEa0-wlquw tools/xenmgr/lib/server/console.py
-40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/xenmgr/lib/server/controller.py
-40c9c469vHh-qLiiubdbKEQbJf18Zw tools/xenmgr/lib/server/cstruct.py
-40d83983OXjt-y3HjSCcuoPp9rzvmw tools/xenmgr/lib/server/domain.py
-40c9c469yrm31i60pGKslTi2Zgpotg tools/xenmgr/lib/server/messages.py
-40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/xenmgr/lib/server/netif.py
-40c9c469ZqILEQ8x6yWy0_51jopiCg tools/xenmgr/lib/server/params.py
-40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/xenmgr/lib/sxp.py
-40d05079aFRp6NQdo5wIh5Ly31c0cg tools/xenmgr/lib/xm/__init__.py
-40cf2937gKQcATgXKGtNeWb1PDH5nA tools/xenmgr/lib/xm/create.py
-40cf2937isyS250zyd0Q2GuEDoNXfQ tools/xenmgr/lib/xm/main.py
-40cf2937PSslwBliN1g7ofDy2H_RhA tools/xenmgr/lib/xm/opts.py
-40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/xenmgr/lib/xm/shutdown.py
-40c9c469kT0H9COWzA4XzPBjWK0WsA tools/xenmgr/netfix
-40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/xenmgr/setup.py
-40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/xenmgr/xend
-40c9c469JkN47d1oXi-e0RjAP-C6uQ tools/xenmgr/xenmgrd
-40cf2937dqM1jWW87O5OoOYND8leuA tools/xenmgr/xm
+40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend-old/Makefile
+4055ad95Se-FqttgxollqOAAHB94zA tools/xend-old/lib/__init__.py
+4092738fMRGC9fFBcPRCWaJaj9U3ag tools/xend-old/lib/blkif.py
+4055ad97wMLUj0BZT0e_T0EwQN0Bvw tools/xend-old/lib/console.py
+4048c0ddsF0WrU7HUzTvg1MJoCIfWg tools/xend-old/lib/domain_controller.h
+4054a301VEag2GwrBrFBna5U1BGlLA tools/xend-old/lib/main.py
+4055ad9ah9IuC3sJT2c_gYIFY5Tw_g tools/xend-old/lib/manager.py
+409ba2e729HhE7fEra4B5EqX-F8Xzw tools/xend-old/lib/netif.py
+40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend-old/lib/utils.c
+4054a2fdkdATEnRw-U7AUlgu-6JiUA tools/xend-old/setup.py
+4056cd26Qyp09iNoOjrvzg8KYzSqOw tools/xend-old/xend
 403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
 40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats
 4050c413PhhLNAYk3TEwP37i_iLw9Q tools/xentrace/xentrace.8
 403a3edbVpV2E_wq1zeEkJ_n4Uu2eg tools/xentrace/xentrace.c
 403a3edblCUrzSj0mmKhO5HOPrOrSQ tools/xentrace/xentrace_format
 4050c413NtuyIq5lsYJV4P7KIjujXw tools/xentrace/xentrace_format.1
+40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/xu/lib/__init__.py
+40dc4076pVeE1kEEWzcUaNZin65kCA tools/xu/lib/domain_controller.h
+40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/xu/lib/xu.c
+40dc4076FyWUYS2nX9YufgglUzKX2A tools/xu/setup.py
 3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
 3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile
 3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen/Rules.mk
index 6009671a4d86dd6ae4904ab364d7e82c237e8108..c29bd1723e3c67658639788b5e1da9bd974908fd 100644 (file)
@@ -13,7 +13,7 @@
 
 /* include the hypervisor interface */
 #include <hypervisor-ifs/hypervisor-if.h>
-#include "../../../tools/xend/lib/domain_controller.h"
+#include "../../../tools/xu/lib/domain_controller.h"
 
 /*
  * a placeholder for the start of day information passed up from the hypervisor
index 54dbaaaca7808ad04ed91d8bfd94637993ed2d92..19d30ddc0b604c6dd3abd4238aa8efce6b250f43 100755 (executable)
@@ -114,7 +114,7 @@ relative_lndir ../../../${RS}/../xen/include/hypervisor-ifs
 
 # Another special symlink: to the shared definitions for the control interface
 cd ..
-ln -sf ../../${RS}/../tools/xend/lib/domain_controller.h
+ln -sf ../../${RS}/../tools/xu/lib/domain_controller.h
 
 # The remainder are the i386 -> xen-i386 links
 ln -sf ../asm-i386/a.out.h 
index 658ff284d1ac480c34cd071af80e101f87e48af3..69b05709f6a725afc25a4a49798c599bc22bf894 100644 (file)
@@ -1,21 +1,22 @@
 
 all:   
        $(MAKE) -C xc
+       $(MAKE) -C xu
        $(MAKE) -C misc
        $(MAKE) -C examples
        $(MAKE) -C xentrace
        $(MAKE) -C xenctl
-       $(MAKE) -C xend
-       $(MAKE) -C xenmgr
+       $(MAKE) -C xen
 
 install: all
        $(MAKE) -C xc install
+       $(MAKE) -C xu install
        $(MAKE) -C misc install
+       $(MAKE) -C xenctl install
        $(MAKE) -C examples install
        $(MAKE) -C xentrace install
        $(MAKE) -C xenctl install
-       $(MAKE) -C xend install
-       $(MAKE) -C xenmgr install
+       $(MAKE) -C xen install
 
 dist: $(TARGET)
        $(MAKE) prefix=`pwd`/../../install dist=yes install
@@ -23,10 +24,10 @@ dist: $(TARGET)
 
 clean:
        $(MAKE) -C xc clean
+       $(MAKE) -C xu clean
        $(MAKE) -C misc clean
        $(MAKE) -C examples clean
        $(MAKE) -C xentrace clean
        $(MAKE) -C xenctl clean
-       $(MAKE) -C xend clean
-       $(MAKE) -C xenmgr clean
+       $(MAKE) -C xen clean
 
index 36e9cab93f35af3aeabfe25ee6a6ade9cd276c01..69651f2152ffc222eee90fad4cf12a25c0a315bb 100644 (file)
@@ -3,7 +3,7 @@ CC         = gcc
 CFLAGS     = -Wall -O3 
 EXTRA_INC  = -I../../xen/include/hypervisor-ifs
 EXTRA_INC += -I../../linux-xen-sparse/include -I../xc/lib
-EXTRA_INC += -I../xend/lib
+EXTRA_INC += -I../xu/lib
 
 HDRS     = $(wildcard *.h)
 SRCS     = $(wildcard *.c)
index 7a6fd2fa12ace526402d90dd393ba80e84df8e76..271a9c470372c51d534e79e0930e7f47ed046aa6 100644 (file)
@@ -6,7 +6,7 @@ SONAME   = libxc.so.$(MAJOR)
 CC       = gcc
 CFLAGS   = -c -Werror -O3 -fno-strict-aliasing
 CFLAGS  += -I../../../xen/include/hypervisor-ifs
-CFLAGS  += -I../../xend/lib
+CFLAGS  += -I../../xu/lib
 CFLAGS  += -I../../../linux-xen-sparse/include
 
 HDRS     = $(wildcard *.h)
index 299202609e5451e70bf467f6603ec000c4b312d7..b52114aab256ab391b17c4d95fa5368281d87a89 100644 (file)
@@ -20,6 +20,8 @@
 #define PyMODINIT_FUNC DL_EXPORT(void)
 #endif
 
+#define XENPKG "xen.ext.xc"
+
 static PyObject *xc_error, *zero;
 
 typedef struct {
@@ -187,112 +189,73 @@ static PyObject *pyxc_domain_getinfo(PyObject *self,
     return list;
 }
 
-static PyObject *pyxc_linux_save(PyObject *self,
-                                 PyObject *args,
-                                 PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32   dom;
-    char *state_file;
-    int   progress = 1, live = -1, debug = 0;
-    unsigned int flags = 0;
-
-    static char *kwd_list[] = { "dom", "state_file", "progress", 
-                                "live", "debug", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|iii", kwd_list, 
-                                      &dom, &state_file, &progress, 
-                                      &live, &debug) )
-        return NULL;
-
-    if (progress)  flags |= XCFLAGS_VERBOSE;
-    if (live == 1) flags |= XCFLAGS_LIVE;
-    if (debug)     flags |= XCFLAGS_DEBUG;
-
-    if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 )
-    {
+static PyObject *tcp_save(XcObject *xc, u32 dom, char *url, unsigned flags){
 #define max_namelen 64
-        char server[max_namelen];
-        char *port_s;
-        int port=777;
-        int sd = -1;
-        struct hostent *h;
-        struct sockaddr_in s;
-        int sockbufsize;
-        int rc = -1;
-
-        int writerfn(void *fd, const void *buf, size_t count)
-        {
-            int tot = 0, rc;
-            do {
-                rc = write( (int) fd, ((char*)buf)+tot, count-tot );
-                if ( rc < 0 ) { perror("WRITE"); return rc; };
-                tot += rc;
-            }
-            while ( tot < count );
-            return 0;
-        }
-
-        if (live == -1) flags |= XCFLAGS_LIVE; /* default to live for tcp */
-
-        strncpy( server, state_file+strlen("tcp://"), max_namelen);
-        server[max_namelen-1]='\0';
-        if ( (port_s = strchr(server,':')) != NULL )
-        {
-            *port_s = '\0';
-            port = atoi(port_s+1);
+    char server[max_namelen];
+    char *port_s;
+    int port=777;
+    int sd = -1;
+    struct hostent *h;
+    struct sockaddr_in s;
+    int sockbufsize;
+    int rc = -1;
+    
+    int writerfn(void *fd, const void *buf, size_t count) {
+        int tot = 0, rc;
+        do {
+            rc = write( (int) fd, ((char*)buf)+tot, count-tot );
+            if ( rc < 0 ) { perror("WRITE"); return rc; };
+            tot += rc;
         }
-
-        printf("X server=%s port=%d\n",server,port);
-        h = gethostbyname(server);
-        sd = socket (AF_INET,SOCK_STREAM,0);
-        if ( sd < 0 )
-            goto serr;
-        s.sin_family = AF_INET;
-        bcopy ( h->h_addr, &(s.sin_addr.s_addr), h->h_length);
-        s.sin_port = htons(port);
-        if ( connect(sd, (struct sockaddr *) &s, sizeof(s)) ) 
-            goto serr;
-
-        sockbufsize=128*1024;
-        if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, 
-                        &sockbufsize, sizeof sockbufsize) < 0 ) 
-            goto serr;
-
-        if ( xc_linux_save(xc->xc_handle, dom, flags, 
-                           writerfn, (void*)sd) == 0 )
-        {
-            if ( read( sd, &rc, sizeof(int) ) != sizeof(int) )
-                goto serr;
+        while ( tot < count );
+        return 0;
+    }
+    
+    strncpy( server, url+strlen("tcp://"), max_namelen);
+    server[max_namelen-1]='\0';
+    if ( (port_s = strchr(server,':')) != NULL ) {
+        *port_s = '\0';
+        port = atoi(port_s+1);
+    }
+    printf("X server=%s port=%d\n",server,port);
+    h = gethostbyname(server);
+    sd = socket(AF_INET, SOCK_STREAM,0);
+    if (sd < 0) goto serr;
+    s.sin_family = AF_INET;
+    bcopy ( h->h_addr, &(s.sin_addr.s_addr), h->h_length);
+    s.sin_port = htons(port);
+    if ( connect(sd, (struct sockaddr *) &s, sizeof(s)) ) goto serr;
+    sockbufsize=128*1024;
+    if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &sockbufsize, sizeof sockbufsize) < 0 ) goto serr;
+
+    if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, (void*)sd) == 0 ) {
+        if ( read( sd, &rc, sizeof(int) ) != sizeof(int) ) goto serr;
   
-            if ( rc == 0 )
-            {
+        if ( rc == 0 ) {
                 printf("Migration succesful -- destroy local copy\n");
                 xc_domain_destroy(xc->xc_handle, dom);
                 close(sd);
                 Py_INCREF(zero);
                 return zero;
-            }
-            else
-                errno = rc;
+        } else {
+            errno = rc;
         }
+    }
 
-    serr:
-        printf("Migration failed -- restart local copy\n");
-        xc_domain_unpause(xc->xc_handle, dom);
-        PyErr_SetFromErrno(xc_error);
-        if ( sd >= 0 ) close(sd);
-        return NULL;
-    }    
-    else
-    {
+  serr:
+    printf("Migration failed -- restart local copy\n");
+    xc_domain_unpause(xc->xc_handle, dom);
+    PyErr_SetFromErrno(xc_error);
+    if ( sd >= 0 ) close(sd);
+    return NULL;
+
+}
+
+static PyObject *file_save(XcObject *xc, u32 dom, char *state_file, unsigned flags){
         int fd = -1;
         gzFile gfd = NULL;
 
-        int writerfn(void *fd, const void *buf, size_t count)
-        {
+        int writerfn(void *fd, const void *buf, size_t count) {
             int rc;
             while ( ((rc = gzwrite( (gzFile*)fd, (void*)buf, count)) == -1) && 
                     (errno = EINTR) )
@@ -300,30 +263,24 @@ static PyObject *pyxc_linux_save(PyObject *self,
             return ! (rc == count);
         }
 
-        if (strncmp(state_file,"file:",strlen("file:")) == 0)
+        if (strncmp(state_file,"file:",strlen("file:")) == 0){
             state_file += strlen("file:");
+        }
 
-        if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
-        {
+        if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 ) {
             perror("Could not open file for writing");
             goto err;
         }
-
         /*
          * Compression rate 1: we want speed over compression. 
          * We're mainly going for those zero pages, after all.
          */
-
-        if ( (gfd = gzdopen(fd, "wb1")) == NULL )
-        {
+        if ( (gfd = gzdopen(fd, "wb1")) == NULL ) {
             perror("Could not allocate compression state for state file");
             close(fd);
             goto err;
         }
-
-
-        if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, gfd) == 0 )
-        {
+        if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, gfd) == 0 ) {
             /* kill domain. We don't want to do this for checkpointing, but
                if we don't do it here I think people will hurt themselves
                by accident... */
@@ -337,14 +294,45 @@ static PyObject *pyxc_linux_save(PyObject *self,
 
     err:
         PyErr_SetFromErrno(xc_error);
-        if ( gfd != NULL )
-            gzclose(gfd);
-        if ( fd >= 0 )
-            close(fd);
+        if ( gfd != NULL ) gzclose(gfd);
+        if ( fd >= 0 ) close(fd);
         unlink(state_file);
         return NULL;
-    }
+}
+
+static PyObject *pyxc_linux_save(PyObject *self,
+                                 PyObject *args,
+                                 PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
 
+    u32   dom;
+    char *state_file;
+    int   progress = 1, live = -1, debug = 0;
+    unsigned int flags = 0;
+    PyObject *val = NULL;
+
+    static char *kwd_list[] = { "dom", "state_file", "progress", 
+                                "live", "debug", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|iii", kwd_list, 
+                                      &dom, &state_file, &progress, 
+                                      &live, &debug) )
+        goto exit;
+
+    if (progress)  flags |= XCFLAGS_VERBOSE;
+    if (live == 1) flags |= XCFLAGS_LIVE;
+    if (debug)     flags |= XCFLAGS_DEBUG;
+
+    if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 ) {
+        /* default to live for tcp */
+        if (live == -1) flags |= XCFLAGS_LIVE;
+        val = tcp_save(xc, dom, state_file, flags);
+    } else {
+        val = file_save(xc, dom, state_file, flags);
+    }
+  exit:
+    return val;
 }
 
 static PyObject *pyxc_linux_restore(PyObject *self,
@@ -1335,18 +1323,18 @@ static PyTypeObject PyXcType = {
 };
 
 static PyMethodDef PyXc_methods[] = {
-    { "new", PyXc_new, METH_VARARGS, "Create a new Xc object." },
+    { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
     { NULL, NULL, 0, NULL }
 };
 
-PyMODINIT_FUNC initXc(void)
+PyMODINIT_FUNC initxc(void)
 {
     PyObject *m, *d;
 
-    m = Py_InitModule("Xc", PyXc_methods);
+    m = Py_InitModule(XENPKG, PyXc_methods);
 
     d = PyModule_GetDict(m);
-    xc_error = PyErr_NewException("Xc.error", NULL, NULL);
+    xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
     PyDict_SetItemString(d, "error", xc_error);
 
     zero = PyInt_FromLong(0);
index 84eb6239a241b01a3e2c0bc4b83eb3d28d7a18b4..b295ed295b2c7cd81a01bbf79ce6f3871ca5a1e6 100644 (file)
@@ -1,11 +1,14 @@
 
 from distutils.core import setup, Extension
 
-module = Extension("Xc",
+module = Extension("xc",
                    extra_compile_args   = ["-fno-strict-aliasing"],
                    include_dirs         = ["../lib"],
                    library_dirs         = ["../lib"],
                    libraries            = ["xc"],
                    sources              = ["Xc.c"])
 
-setup(name = "Xc", version = "1.0", ext_modules = [module])
+setup(name = "xc",
+      version = "1.0",
+      ext_package = "xen.ext",
+      ext_modules = [module])
diff --git a/tools/xen/Makefile b/tools/xen/Makefile
new file mode 100644 (file)
index 0000000..642cd22
--- /dev/null
@@ -0,0 +1,19 @@
+
+all:
+       python setup.py build
+
+install: all
+       if [ "$(prefix)" = "" ]; then                   \
+           python setup.py install;                    \
+       elif [ "$(dist)" = "yes" ]; then                \
+           python setup.py install --home="$(prefix)"; \
+       else                                            \
+           python setup.py install --root="$(prefix)"; \
+       fi
+       mkdir -p $(prefix)/usr/sbin
+       install -m0755 xend $(prefix)/usr/sbin
+       install -m0755 netfix $(prefix)/usr/sbin
+       install -m0755 xm $(prefix)/usr/sbin
+
+clean:
+       rm -rf build *.pyc *.pyo *.o *.a *~
diff --git a/tools/xen/lib/__init__.py b/tools/xen/lib/__init__.py
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/tools/xen/lib/xend/Args.py b/tools/xen/lib/xend/Args.py
new file mode 100644 (file)
index 0000000..527e841
--- /dev/null
@@ -0,0 +1,126 @@
+import sxp
+
+class ArgError(StandardError):
+    pass
+
+class Args:
+    """Argument encoding support for HTTP.
+    """
+    
+    def __init__(self, paramspec, keyspec):
+        self.arg_ord = []
+        self.arg_dict = {}
+        self.key_ord = []
+        self.key_dict = {}
+        for (name, type) in paramspec:
+                self.arg_ord.append(name)
+                self.arg_dict[name] = type
+        for (name, type) in keyspec:
+                self.key_ord.append(name)
+                self.key_dict[name] = type
+
+    def get_args(self, d, xargs=None):
+        args = {}
+        keys = {}
+        params = []
+        if xargs:
+            self.split_args(xargs, args, keys)
+        self.split_args(d, args, keys)
+        for a in self.arg_ord:
+            if a in args:
+                params.append(args[a])
+            else:
+                raise ArgError('Missing parameter: %s' % a)
+        return (params, keys)
+
+    def split_args(self, d, args, keys):
+        for (k, v) in d.items():
+            if k in self.arg_dict:
+                type = self.arg_dict[k]
+                val = self.coerce(type, v)
+                args[k] = val
+            elif k in self.key_dict:
+                type = self.key_dict[k]
+                val = self.coerce(type, v)
+                keys[k] = val
+            else:
+                raise ArgError('Invalid parameter: %s' % k)
+
+    def get_form_args(self, f, xargs=None):
+        d = {}
+        for (k, v) in f.items():
+            n = len(v)
+            if ((k not in self.arg_dict) and
+                (k not in self.key_dict)):
+                continue
+            if n == 0:
+                continue
+            elif n == 1:
+                d[k] = v[0]
+            else:
+                raise ArgError('Too many values for %s' % k)
+        return self.get_args(d, xargs=xargs)
+
+    def coerce(self, type, v):
+        try:
+            if type == 'int':
+                return int(v)
+            if type == 'str':
+                return str(v)
+            if type == 'sxpr':
+                return self.sxpr(v)
+        except ArgError:
+            raise
+        except StandardError, ex:
+            raise ArgError(str(ex))
+
+    def sxpr(self, v):
+        if instanceof(v, types.ListType):
+            return v
+        if instanceof(v, types.File) or hasattr(v, 'readline'):
+            return sxpr_file(v)
+        if instanceof(v, types.StringType):
+            return sxpr_file(StringIO(v))
+        return str(v)
+
+    def sxpr_file(self, fin):
+        try:
+            vals = sxp.parse(fin)
+        except:
+            raise ArgError('Coercion to sxpr failed')
+        if len(vals) == 1:
+            return vals[0]
+        else:
+            raise ArgError('Too many sxprs')
+
+    def call_with_args(self, fn, args, xargs=None):
+        (params, keys) = self.get_args(args, xargs=xargs)
+        fn(*params, **keys)
+
+    def call_with_form_args(self, fn, fargs, xargs=None):
+        (params, keys) = self.get_form_args(fargs, xargs=xargs)
+        fn(*params, **keys)
+
+class ArgFn(Args):
+    """Represent a remote HTTP operation as a function.
+    Used on the client.
+    """
+
+    def __init__(self, fn, paramspec, keyspec={}):
+        Args.__init__(self, paramspec, keyspec)
+        self.fn = fn
+
+    def __call__(self, fargs, xargs=None):
+        return self.call_with_args(self.fn, fargs, xargs=xargs)
+    
+class FormFn(Args):
+    """Represent an operation as a function over a form.
+    Used in the HTTP server.
+    """
+
+    def __init__(self, fn, paramspec, keyspec={}):
+        Args.__init__(self, paramspec, keyspec)
+        self.fn = fn
+
+    def __call__(self, fargs, xargs=None):
+        return self.call_with_form_args(self.fn, fargs, xargs=xargs)
diff --git a/tools/xen/lib/xend/EventServer.py b/tools/xen/lib/xend/EventServer.py
new file mode 100644 (file)
index 0000000..20c567a
--- /dev/null
@@ -0,0 +1,215 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Simple publish/subscribe event server.
+
+"""
+import string
+
+from twisted.internet import reactor
+
+# subscribe a.b.c h: map a.b.c -> h
+# subscribe a.b.* h: map a.b.* -> h
+# subscribe a.b.? h: map a.b.? -> h
+#
+# for event a.b.c.d:
+#
+# lookup a.b.c.d, call handlers
+#
+# lookup a.b.c.?, call handlers
+#
+# lookup a.b.c.d.*, call handlers
+# lookup a.b.c.*, call handlers
+# lookup a.b.*, call handlers
+# lookup a.*, call handlers
+# lookup *, call handlers
+
+# a.b.c.d = (a b c d)
+# a.b.c.? = (a b c _)
+# a.b.c.* = (a b c . _)
+
+class EventServer:
+
+    DOT = '.'
+    QUERY = '?'
+    DOT_QUERY = DOT + QUERY
+    STAR = '*'
+    DOT_STAR = DOT + STAR
+
+    def __init__(self, run=0):
+        self.handlers = {}
+        self.run = run
+        self.queue = []
+
+    def start(self):
+        """Enable event handling. Sends any queued events.
+        """
+        self.run = 1
+        for (e,v) in self.queue:
+            self.inject(e, v)
+        self.queue = []
+
+    def stop(self):
+        """Suspend event handling. Events injected while suspended
+        are queued until we are started again.
+        """
+        self.run = 0
+
+    def subscribe(self, event, handler):
+        """Subscribe to an event. For example 'a.b.c.d'.
+        A subcription like 'a.b.c.?' ending in '?' matches any value
+        for the '?'. A subscription like 'a.b.c.*' ending in '*' matches
+        any event type with the same prefix, 'a.b.c' in this case.
+
+        event  event name
+        handler event handler fn(event, val)
+        """
+        hl = self.handlers.get(event)
+        if hl is None:
+            self.handlers[event] = [handler]
+        else:
+            hl.append(handler)
+
+    def unsubscribe_all(self, event=None):
+        """Unsubscribe all handlers for a given event, or all handlers.
+
+        event  event (optional)
+        """
+        if event == None:
+            self.handlers.clear()
+        elif event in self.handlers:
+            del self.handlers[event]
+        
+    def unsubscribe(self, event, handler):
+        """Unsubscribe a given event and handler.
+
+        event  event
+        handler handler
+        """
+        hl = self.handlers.get(event)
+        if hl is None:
+            return
+        if handler in hl:
+            hl.remove(handler)
+
+    def inject(self, event, val, async=1):
+        """Inject an event. Handlers for it are called if running, otherwise
+        it is queued.
+
+        event  event type
+        val    event value
+        """
+        if self.run:
+            if async:
+                reactor.callLater(0, self.call_handlers, event, val)
+            else:
+                self.notify_handlers(event, val)
+        else:
+            self.queue.append( (event, val) )
+
+    def call_handlers(self, event, val):
+        """Internal method to call event handlers.
+        """
+        #print ">event", event, val
+        self.call_event_handlers(event, event, val)
+        self.call_query_handlers(event, val)
+        self.call_star_handlers(event, val)
+
+    def call_event_handlers(self, key, event, val):
+        """Call the handlers for an event.
+        It is safe for handlers to subscribe or unsubscribe.
+
+        key    key for handler list
+        event  event type
+        val    event value
+        """
+        hl = self.handlers.get(key)
+        if hl is None:
+            return
+        # Copy the handler list so that handlers can call
+        # subscribe/unsubscribe safely - python list iteration
+        # is not safe against list modification.
+        for h in hl[:]:
+            try:
+                h(event, val)
+            except:
+                pass
+        
+    def call_query_handlers(self, event, val):
+        """Call regex handlers for events matching 'event' that end in '?'.
+
+        event  event type
+        val    event value
+        """
+        dot_idx = event.rfind(self.DOT)
+        if dot_idx == -1:
+            self.call_event_handlers(self.QUERY, event, val)
+        else:
+            event_query = event[0:dot_idx] + self.DOT_QUERY
+            self.call_event_handlers(event_query, event, val)
+
+    def call_star_handlers(self, event, val):
+        """Call regex handlers for events matching 'event' that end in '*'.
+
+        event  event type
+        val    event value
+        """
+        etype = string.split(event, self.DOT)
+        for i in range(len(etype), 0, -1):
+            event_star = self.DOT.join(etype[0:i]) + self.DOT_STAR
+            self.call_event_handlers(event_star, event, val)
+        self.call_event_handlers(self.STAR, event, val)       
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = EventServer()
+        inst.start()
+    return inst
+
+def main():
+    def sys_star(event, val):
+        print 'sys_star', event, val
+
+    def sys_foo(event, val):
+        print 'sys_foo', event, val
+        s.unsubscribe('sys.foo', sys_foo)
+
+    def sys_foo2(event, val):
+        print 'sys_foo2', event, val
+
+    def sys_bar(event, val):
+        print 'sys_bar', event, val
+
+    def sys_foo_bar(event, val):
+        print 'sys_foo_bar', event, val
+
+    def foo_bar(event, val):
+        print 'foo_bar', event, val
+
+    s = EventServer()
+    s.start()
+    s.subscribe('sys.*', sys_star)
+    s.subscribe('sys.foo', sys_foo)
+    s.subscribe('sys.foo', sys_foo2)
+    s.subscribe('sys.bar', sys_bar)
+    s.subscribe('sys.foo.bar', sys_foo_bar)
+    s.subscribe('foo.bar', foo_bar)
+    s.inject('sys.foo', 'hello')
+    print
+    s.inject('sys.bar', 'hello again')
+    print
+    s.inject('sys.foo.bar', 'hello again')
+    print
+    s.inject('foo.bar', 'hello again')
+    print
+    s.inject('foo', 'hello again')
+    print
+    s.start()
+    s.unsubscribe('sys.*', sys_star)
+    s.unsubscribe_all('sys.*')
+    s.inject('sys.foo', 'hello')
+
+if __name__ == "__main__":
+    main()
+
diff --git a/tools/xen/lib/xend/EventTypes.py b/tools/xen/lib/xend/EventTypes.py
new file mode 100644 (file)
index 0000000..6350baa
--- /dev/null
@@ -0,0 +1,34 @@
+#   Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+## XEND_DOMAIN_CREATE = "xend.domain.create": dom
+## create: 
+## xend.domain.destroy: dom, reason:died/crashed
+## xend.domain.up ?
+
+## xend.domain.unpause: dom
+## xend.domain.pause: dom
+## xend.domain.shutdown: dom
+## xend.domain.destroy: dom
+
+## xend.domain.migrate.begin: dom, to
+## Begin tells: src host, src domain uri, dst host. Dst id known?
+## err: src host, src domain uri, dst host, dst id if known, status (of domain: ok, dead,...), reason
+## end: src host, src domain uri, dst host, dst uri
+
+## Events for both ends of migrate: for exporter and importer?
+## Include migrate id so can tie together.
+## Have uri /xend/migrate/<id> for migrate info (migrations in progress).
+
+## (xend.domain.migrate.begin (src <host>) (src.domain <id>)
+##                            (dst <host>) (id <migrate id>))
+## xend.domain.migrate.end:
+## (xend.domain.migrate.end (domain <id>) (to <host>)
+
+## xend.node.up:  xend uri
+## xend.node.down: xend uri
+
+## xend.error ?
+
+## format:
+
diff --git a/tools/xen/lib/xend/PrettyPrint.py b/tools/xen/lib/xend/PrettyPrint.py
new file mode 100644 (file)
index 0000000..9e91b11
--- /dev/null
@@ -0,0 +1,299 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""General pretty-printer, including support for SXP.
+
+"""
+import sys
+import types
+import StringIO
+import sxp
+
+class PrettyItem:
+
+    def __init__(self, width):
+        self.width = width
+
+    def insert(self, block):
+        block.addtoline(self)
+
+    def get_width(self):
+        return self.width
+
+    def output(self, out):
+        print '***PrettyItem>output>', self
+        pass
+
+    def prettyprint(self, out, width):
+        print '***PrettyItem>prettyprint>', self
+        return width
+
+class PrettyString(PrettyItem):
+
+    def __init__(self, x):
+        PrettyItem.__init__(self, len(x))
+        self.value = x
+
+    def output(self, out):
+        out.write(self.value)
+
+    def prettyprint(self, line):
+        line.output(self)
+
+    def show(self, out):
+        print >> out, ("(string (width %d) '%s')" % (self.width, self.value))
+
+class PrettySpace(PrettyItem):
+
+    def output(self, out):
+        out.write(' ' * self.width)
+
+    def prettyprint(self, line):
+        line.output(self)
+
+    def show(self, out):
+        print >> out, ("(space (width %d))" % self.width)
+        
+class PrettyBreak(PrettyItem):
+
+    def __init__(self, width, indent):
+        PrettyItem.__init__(self, width)
+        self.indent = indent
+        self.space = 0
+        self.active = 0
+
+    def output(self, out):
+        out.write(' ' * self.width)
+
+    def prettyprint(self, line):
+        if line.breaks(self.space):
+            self.active = 1
+            line.newline(self.indent)
+        else:
+            line.output(self)
+
+    def show(self, out):
+        print >> out, ("(break (width %d) (indent %d) (space %d) (active %d))"
+                       % (self.width, self.indent, self.space, self.lspace, self.active))
+
+class PrettyNewline(PrettySpace):
+
+    def __init__(self, indent):
+        PrettySpace.__init__(self, indent)
+
+    def insert(self, block):
+        block.newline()
+        block.addtoline(self)
+
+    def output(self, out):
+        out.write(' ' * self.width)
+
+    def prettyprint(self, line):
+        line.newline(0)
+        line.output(self)
+
+    def show(self, out):
+        print >> out, ("(nl (indent %d))" % self.indent)
+
+class PrettyLine(PrettyItem):
+    def __init__(self):
+        PrettyItem.__init__(self, 0)
+        self.content = []
+
+    def write(self, x):
+        self.content.append(x)
+
+    def end(self):
+        width = 0
+        lastwidth = 0
+        lastbreak = None
+        for x in self.content:
+            if isinstance(x, PrettyBreak):
+                if lastbreak:
+                    lastbreak.space = (width - lastwidth)
+                lastbreak = x
+                lastwidth = width
+            width += x.get_width()
+        if lastbreak:
+            lastbreak.space = (width - lastwidth)
+        self.width = width
+    def prettyprint(self, line):
+        for x in self.content:
+            x.prettyprint(line)
+
+    def show(self, out):
+        print >> out, '(LINE (width %d)' % self.width
+        for x in self.content:
+            x.show(out)
+        print >> out, ')'
+
+class PrettyBlock(PrettyItem):
+
+    def __init__(self, all=0, parent=None):
+        self.width = 0
+        self.lines = []
+        self.parent = parent
+        self.indent = 0
+        self.all = all
+        self.broken = 0
+        self.newline()
+
+    def add(self, item):
+        item.insert(self)
+
+    def end(self):
+        self.width = 0
+        for l in self.lines:
+            l.end()
+            if self.width < l.width:
+                self.width = l.width
+
+    def breaks(self, n):
+        return self.all and self.broken
+
+    def newline(self):
+        self.lines.append(PrettyLine())
+
+    def addtoline(self, x):
+        self.lines[-1].write(x)
+
+    def prettyprint(self, line):
+        self.indent = line.used
+        line.block = self
+        if not line.fits(self.width):
+            self.broken = 1
+        for l in self.lines:
+            l.prettyprint(line)
+        line.block = self.parent
+
+    def show(self, out):
+        print >> out, ('(BLOCK (width %d) (indent %d) (all %d) (broken %d)' %
+                       (self.width, self.indent, self.all, self.broken))
+        for l in self.lines:
+            l.show(out)
+        print >> out, ')'
+
+class Line:
+
+    def __init__(self, out, width):
+        self.out = out
+        self.width = width
+        self.used = 0
+        self.space = self.width
+
+    def newline(self, indent):
+        indent += self.block.indent
+        self.out.write('\n')
+        self.out.write(' ' * indent)
+        self.used = indent
+        self.space = self.width - self.used
+
+    def fits(self, n):
+        return self.space - n >= 0
+
+    def breaks(self, n):
+        return self.block.breaks(n) or not self.fits(n)
+
+    def output(self, x):
+        n = x.get_width()
+        self.space -= n
+        self.used += n
+        if self.space < 0:
+            self.space = 0
+        x.output(self.out)
+
+class PrettyPrinter:
+    """A prettyprinter based on what I remember of Derek Oppen's
+    prettyprint algorithm from TOPLAS way back.
+    """
+
+    def __init__(self, width=40):
+        self.width = width
+        self.block = None
+        self.top = None
+
+    def write(self, x):
+        self.block.add(PrettyString(x))
+
+    def add(self, item):
+        self.block.add(item)
+
+    def addbreak(self, width=1, indent=4):
+        self.add(PrettyBreak(width, indent))
+
+    def addspace(self, width=1):
+        self.add(PrettySpace(width))
+
+    def addnl(self, indent=0):
+        self.add(PrettyNewline(indent))
+
+    def begin(self, all=0):
+        block = PrettyBlock(all=all, parent=self.block)
+        self.block = block
+
+    def end(self):
+        self.block.end()
+        if self.block.parent:
+            self.block.parent.add(self.block)
+        else:
+            self.top = self.block
+        self.block = self.block.parent
+
+    def prettyprint(self, out=sys.stdout):
+        line = Line(out, self.width)
+        self.top.prettyprint(line)
+
+class SXPPrettyPrinter(PrettyPrinter):
+    """An SXP prettyprinter.
+    """
+    
+    def pstring(self, x):
+        io = StringIO.StringIO()
+        sxp.show(x, out=io)
+        io.seek(0)
+        val = io.getvalue()
+        io.close()
+        return val
+
+    def pprint(self, l):
+        if isinstance(l, types.ListType):
+            self.begin(all=1)
+            self.write('(')
+            i = 0
+            for x in l:
+                if(i): self.addbreak()
+                self.pprint(x)
+                i += 1
+            self.addbreak(width=0, indent=0)
+            self.write(')')
+            self.end()
+        else:
+            self.write(self.pstring(l))
+
+def prettyprint(sxpr, out=sys.stdout, width=80):
+    """Prettyprint an SXP form.
+
+    sxpr       s-expression
+    out                destination
+    width      maximum output width
+    """
+    if isinstance(sxpr, types.ListType):
+        pp = SXPPrettyPrinter(width=width)
+        pp.pprint(sxpr)
+        pp.prettyprint(out=out)
+    else:
+        sxp.show(sxpr, out=out)
+    print >> out
+
+def main():
+    pin = sxp.Parser()
+    while 1:
+        buf = sys.stdin.read(100)
+        pin.input(buf)
+        if buf == '': break
+    l = pin.get_val()
+    prettyprint(l, width=80)
+
+if __name__ == "__main__":
+    main()
+    
diff --git a/tools/xen/lib/xend/XendBridge.py b/tools/xen/lib/xend/XendBridge.py
new file mode 100644 (file)
index 0000000..f158455
--- /dev/null
@@ -0,0 +1,193 @@
+"""Bridge control utilities.
+"""
+import os
+import os.path
+import re
+import sys
+
+from xen.xend import XendRoot
+xroot = XendRoot.instance()
+
+os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin'
+CMD_IFCONFIG = 'ifconfig'
+CMD_ROUTE    = 'route'
+CMD_BRCTL    = 'brctl'
+CMD_IPTABLES = "iptables"
+
+DEFAULT_BRIDGE = 'nbe-br'
+DEFAULT_INTERFACE = 'eth0'
+
+opts = None
+
+class Opts:
+
+    def __init__(self, defaults):
+        for (k, v) in defaults.items():
+            setattr(self, k, v)
+        pass
+
+def cmd(p, s):
+    """Print and execute command 'p' with args 's'.
+    """
+    global opts
+    c = p + ' ' + s
+    if opts.verbose: print c
+    if not opts.dryrun:
+        os.system(c)
+
+def default_bridge():
+    return xroot.get_config_value('bridge', DEFAULT_BRIDGE)
+
+def default_interface():
+    return xroot.get_config_value('interface', DEFAULT_INTERFACE)
+
+def vif_dev(dom, vif):
+    """Return the name of the network interface for vif on domain dom.
+    """
+    return "vif%d.%d" % (dom, vif)
+
+def vif_bridge_add(dom, vif, bridge=None):
+    """Add the network interface for vif on dom to a bridge.
+    """
+    if not bridge: bridge = default_bridge()
+    d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
+    cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % d)
+    return bridge
+
+def vif_bridge_rem(dom, vif, bridge=None):
+    """Remove the network interface for vif on dom from a bridge.
+    """
+    if not bridge: bridge = default_bridge()
+    print 'vif_bridge_rem>', dom, vif, bridge
+    d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
+    cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % d)
+
+def vif_restrict_addr(dom, vif, addr, delete=0):
+    d = { 'vif': vif_dev(dom, vif), 'addr': addr}
+    if delete:
+        d['flag'] = '-D'
+    else:
+        d['flag'] = '-A'
+    cmd(CMD_IPTABLES, '-P FORWARD DROP')
+    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-in %(vif)s -s %(addr)s -j ACCEPT' % d)
+    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-out %(vif)s -d %(addr)s -j ACCEPT' % d)
+
+def bridge_create(bridge=None, **kwd):
+    """Create a bridge.
+    Defaults hello time to 0, forward delay to 0 and stp off.
+    """
+    if not bridge: bridge = default_bridge()
+    cmd(CMD_BRCTL, 'addbr %s' % bridge)
+    if kwd.get('hello', None) is None:
+        kwd['hello'] = 0
+    if kwd.get('fd', None) is None:
+        kwd['fd'] = 0
+    if kwd.get('stp', None) is None:
+        kwd['stp'] = 'off'
+    bridge_set(bridge, **kwd)
+
+def bridge_set(bridge, hello=None, fd=None, stp=None):
+    """Set bridge parameters.
+    """
+    if hello is not None:
+        cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello))
+    if fd is not None:
+        cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd))
+    if stp is not None:
+        cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp))
+
+def bridge_del(bridge=None):
+    """Delete a bridge.
+    """
+    if not bridge: bridge = default_bridge()
+    cmd(CMD_BRCTL, 'delbr %s' % bridge)
+
+def routes():
+    """Return a list of the routes.
+    """
+    fin = os.popen(CMD_ROUTE + ' -n', 'r')
+    routes = []
+    for x in fin:
+        if x.startswith('Kernel'): continue
+        if x.startswith('Destination'): continue
+        x = x.strip()
+        y = x.split()
+        z = { 'destination': y[0],
+              'gateway'    : y[1],
+              'mask'       : y[2],
+              'flags'      : y[3],
+              'metric'     : y[4],
+              'ref'        : y[5],
+              'use'        : y[6],
+              'interface'  : y[7] }
+        routes.append(z)
+    return routes
+
+def ifconfig(interface):
+    """Return the ip config for an interface,
+    """
+    fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r')
+    inetre = re.compile('\s*inet\s*addr:(?P<address>\S*)\s*Bcast:(?P<broadcast>\S*)\s*Mask:(?P<mask>\S*)')
+    info = None
+    for x in fin:
+        m = inetre.match(x)
+        if not m: continue
+        info = m.groupdict()
+        info['interface'] = interface
+        break
+    return info
+
+def reconfigure(interface=None, bridge=None):
+    """Reconfigure an interface to be attached to a bridge, and give the bridge
+    the IP address etc. from interface. Move the default route to the interface
+    to the bridge.
+
+    If opts.create is true, creates the bridge.
+    """
+    global opts
+    if not interface: interface = default_interface()
+    if not bridge: bridge = default_bridge()
+    intf_info = ifconfig(interface)
+    if not intf_info:
+        print 'Interface not found:', interface
+        return
+    if opts.create:
+        bridge_create(bridge)
+    #bridge_info = ifconfig(bridge)
+    #if not bridge_info:
+    #    print 'Bridge not found:', bridge
+    #    return
+    route_info = routes()
+    intf_info['bridge'] = bridge
+    intf_info['gateway'] = None
+    for r in route_info:
+        if (r['destination'] == '0.0.0.0' and
+            'G' in r['flags'] and
+            r['interface'] == interface):
+            intf_info['gateway'] = r['gateway']
+    if not intf_info['gateway']:
+        print 'Gateway not found: ', interface
+        return
+    cmd(CMD_IFCONFIG,
+        '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up'
+        % intf_info)
+    cmd(CMD_ROUTE,
+        'add default gateway %(gateway)s dev %(bridge)s'
+        % intf_info)
+    cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info)
+    cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info)
+
+defaults = {
+    'interface': default_interface(),
+    'bridge'   : default_bridge(),
+    'verbose'  : 1,
+    'dryrun'   : 0,
+    'create'   : 0,
+    }
+
+opts = Opts(defaults)
+
+def set_opts(val):
+    global opts
+    opts = val
+    return opts
diff --git a/tools/xen/lib/xend/XendClient.py b/tools/xen/lib/xend/XendClient.py
new file mode 100644 (file)
index 0000000..13dc3db
--- /dev/null
@@ -0,0 +1,311 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Client API for the HTTP interface on xend.
+Callable as a script - see main().
+"""
+import sys
+import httplib
+import types
+from StringIO import StringIO
+import urlparse
+
+from encode import *
+import sxp
+import PrettyPrint
+
+DEBUG = 0
+
+class Foo(httplib.HTTPResponse):
+
+    def begin(self):
+        fin = self.fp
+        while(1):
+            buf = fin.readline()
+            print "***", buf
+            if buf == '':
+                print
+                sys.exit()
+
+
+def sxprio(sxpr):
+    io = StringIO()
+    sxp.show(sxpr, out=io)
+    print >> io
+    io.seek(0)
+    return io
+
+def fileof(val):
+    """Converter for passing configs.
+    Handles lists, files directly.
+    Assumes a string is a file name and passes its contents.
+    """
+    if isinstance(val, types.ListType):
+        return sxprio(val)
+    if isinstance(val, types.StringType):
+        return file(val)
+    if hasattr(val, 'readlines'):
+        return val
+
+# todo: need to sort of what urls/paths are using for objects.
+# e.g. for domains at the moment return '0'.
+# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
+# As an arg, assume abs path is obj uri, otherwise just id.
+
+# Function to convert to full url: Xend.uri(path), e.g.
+# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
+# And should accept urls for ids?
+
+def urljoin(location, root, prefix='', rest=''):
+    prefix = str(prefix)
+    rest = str(rest)
+    base = 'http://' + location + root + prefix
+    url = urlparse.urljoin(base, rest)
+    return url
+
+def nodeurl(location, root, id=''):
+    return urljoin(location, root, 'node/', id)
+
+def domainurl(location, root, id=''):
+    return urljoin(location, root, 'domain/', id)
+
+def consoleurl(location, root, id=''):
+    return urljoin(location, root, 'console/', id)
+
+def deviceurl(location, root, id=''):
+    return urljoin(location, root, 'device/', id)
+
+def vneturl(location, root, id=''):
+    return urljoin(location, root, 'vnet/', id)
+
+def eventurl(location, root, id=''):
+    return urljoin(location, root, 'event/', id)
+
+def xend_request(url, method, data=None):
+    urlinfo = urlparse.urlparse(url)
+    (uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo
+    if DEBUG: print url, urlinfo
+    if uproto != 'http':
+        raise StandardError('Invalid protocol: ' + uproto)
+    if DEBUG: print '>xend_request', ulocation, upath, method, data
+    (hdr, args) = encode_data(data)
+    if data and method == 'GET':
+        upath += '?' + args
+        args = None
+    if method == "POST" and upath.endswith('/'):
+        upath = upath[:-1]
+    if DEBUG: print "ulocation=", ulocation, "upath=", upath, "args=", args
+    #hdr['User-Agent'] = 'Mozilla'
+    #hdr['Accept'] = 'text/html,text/plain'
+    conn = httplib.HTTPConnection(ulocation)
+    #conn.response_class = Foo
+    if DEBUG: conn.set_debuglevel(1)
+    conn.request(method, upath, args, hdr)
+    resp = conn.getresponse()
+    if DEBUG: print resp.status, resp.reason
+    if DEBUG: print resp.msg.headers
+    if resp.status in [204, 404]:
+        return None
+    if resp.status not in [200, 201, 202, 203]:
+        raise RuntimeError(resp.reason)
+    pin = sxp.Parser()
+    data = resp.read()
+    if DEBUG: print "***data" , data
+    if DEBUG: print "***"
+    pin.input(data);
+    pin.input_eof()
+    conn.close()
+    val = pin.get_val()
+    #if isinstance(val, types.ListType) and sxp.name(val) == 'val':
+    #    val = val[1]
+    if isinstance(val, types.ListType) and sxp.name(val) == 'err':
+        raise RuntimeError(val[1])
+    if DEBUG: print '**val='; sxp.show(val); print
+    return val
+
+def xend_get(url, args=None):
+    return xend_request(url, "GET", args)
+
+def xend_call(url, data):
+    return xend_request(url, "POST", data)
+
+class Xend:
+
+    SRV_DEFAULT = "localhost:8000"
+    ROOT_DEFAULT = "/xend/"
+
+    def __init__(self, srv=None, root=None):
+        self.bind(srv, root)
+
+    def bind(self, srv=None, root=None):
+        if srv is None: srv = self.SRV_DEFAULT
+        if root is None: root = self.ROOT_DEFAULT
+        if not root.endswith('/'): root += '/'
+        self.location = srv
+        self.root = root
+
+    def nodeurl(self, id=''):
+        return nodeurl(self.location, self.root, id)
+
+    def domainurl(self, id=''):
+        return domainurl(self.location, self.root, id)
+
+    def consoleurl(self, id=''):
+        return consoleurl(self.location, self.root, id)
+
+    def deviceurl(self, id=''):
+        return deviceurl(self.location, self.root, id)
+
+    def vneturl(self, id=''):
+        return vneturl(self.location, self.root, id)
+
+    def eventurl(self, id=''):
+        return eventurl(self.location, self.root, id)
+
+    def xend(self):
+        return xend_get(urljoin(self.location, self.root))
+
+    def xend_node(self):
+        return xend_get(self.nodeurl())
+
+    def xend_node_cpu_rrobin_slice_set(self, slice):
+        return xend_call(self.nodeurl(),
+                         {'op'      : 'cpu_rrobin_slice_set',
+                          'slice'   : slice })
+    
+    def xend_node_cpu_bvt_slice_set(self, slice):
+        return xend_call(self.nodeurl(),
+                         {'op'      : 'cpu_bvt_slice_set',
+                          'slice'   : slice })
+
+    def xend_domains(self):
+        return xend_get(self.domainurl())
+
+    def xend_domain_create(self, conf):
+        return xend_call(self.domainurl(),
+                         {'op'      : 'create',
+                          'config'  : fileof(conf) })
+
+    def xend_domain(self, id):
+        return xend_get(self.domainurl(id))
+
+    def xend_domain_unpause(self, id):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'unpause'})
+
+    def xend_domain_pause(self, id):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'pause'})
+
+    def xend_domain_shutdown(self, id):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'shutdown'})
+
+    def xend_domain_destroy(self, id):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'destroy'})
+
+    def xend_domain_save(self, id, filename):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'save',
+                          'file'    : filename})
+
+    def xend_domain_restore(self, id, filename):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'restore',
+                          'file'    : filename })
+
+    def xend_domain_migrate(self, id, dst):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'migrate',
+                          'destination': dst})
+
+    def xend_domain_pincpu(self, id, cpu):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'pincpu',
+                          'cpu'     : cpu})
+
+    def xend_domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'cpu_bvt_set',
+                          'mcuadv'  : mvuadv,
+                          'warp'    : warp,
+                          'warpl'   : warpl,
+                          'warpu'   : warpu })
+
+    def xend_domain_cpu_atropos_set(self, id, period, slice, latency, xtratime):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'cpu_atropos_set',
+                          'period'  : period,
+                          'slice'   : slice,
+                          'latency' : latency,
+                          'xtratime': xtratime })
+
+    def xend_domain_vifs(self, id):
+        return xend_get(self.domainurl(id),
+                        { 'op'      : 'vifs' })
+    
+    def xend_domain_vif_ip_add(self, id, vif, ipaddr):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'vif_ip_add',
+                          'vif'     : vif,
+                          'ip'      : ipaddr })
+        
+    def xend_domain_vbds(self, id):
+        return xend_get(self.domainurl(id),
+                        {'op'       : 'vbds'})
+
+    def xend_domain_vbd(self, id, vbd):
+        return xend_get(self.domainurl(id),
+                        {'op'       : 'vbd',
+                         'vbd'      : vbd})
+
+    def xend_consoles(self):
+        return xend_get(self.consoleurl())
+
+    def xend_console(self, id):
+        return xend_get(self.consoleurl(id))
+
+    def xend_vnets(self):
+        return xend_get(self.vneturl())
+
+    def xend_vnet_create(self, conf):
+        return xend_call(self.vneturl(),
+                         {'op': 'create', 'config': fileof(conf) })
+
+    def xend_vnet(self, id):
+        return xend_get(self.vneturl(id))
+
+    def xend_vnet_delete(self, id):
+        return xend_call(self.vneturl(id),
+                         {'op': 'delete'})
+
+    def xend_event_inject(self, sxpr):
+        val = xend_call(self.eventurl(),
+                        {'op': 'inject', 'event': fileof(sxpr) })
+    
+
+def main(argv):
+    """Call an API function:
+    
+    python XendClient.py fn args...
+
+    The leading 'xend_' on the function can be omitted.
+    Example:
+
+    > python XendClient.py domains
+    (domain 0 8)
+    > python XendClient.py domain 0
+    (domain (id 0) (name Domain-0) (memory 128))
+    """
+    server = Xend()
+    fn = argv[1]
+    if not fn.startswith('xend'):
+        fn = 'xend_' + fn
+    args = argv[2:]
+    val = getattr(server, fn)(*args)
+    PrettyPrint.prettyprint(val)
+    print
+
+if __name__ == "__main__":
+    main(sys.argv)
+else:    
+    server = Xend()
diff --git a/tools/xen/lib/xend/XendConsole.py b/tools/xen/lib/xend/XendConsole.py
new file mode 100644 (file)
index 0000000..4420c38
--- /dev/null
@@ -0,0 +1,179 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+import socket
+import xen.ext.xc
+xc = xen.ext.xc.new()
+
+import sxp
+import XendRoot
+xroot = XendRoot.instance()
+import XendDB
+
+import EventServer
+eserver = EventServer.instance()
+
+from xen.xend.server import SrvDaemon
+daemon = SrvDaemon.instance()
+
+class XendConsoleInfo:
+    """Console information record.
+    """
+
+    def __init__(self, console, dom1, port1, dom2, port2, conn=None):
+        self.console = console
+        self.dom1  = int(dom1)
+        self.port1 = int(port1)
+        self.dom2  = int(dom2)
+        self.port2 = int(port2)
+        self.conn  = conn
+        #self.id = "%d.%d-%d.%d" % (self.dom1, self.port1, self.dom2, self.port2)
+        self.id = str(port1)
+
+    def __str__(self):
+        s = "console"
+        s += " id=%s" % self.id
+        s += " src=%d.%d" % (self.dom1, self.port1)
+        s += " dst=%d.%d" % (self.dom2, self.port2)
+        s += " port=%s" % self.console
+        if self.conn:
+            s += " conn=%s:%s" % (self.conn[0], self.conn[1])
+        return s
+
+    def sxpr(self):
+        sxpr = ['console',
+                ['id', self.id],
+                ['src', self.dom1, self.port1],
+                ['dst', self.dom2, self.port2],
+                ['port', self.console],
+                ]
+        if self.conn:
+            sxpr.append(['connected', self.conn[0], self.conn[1]])
+        return sxpr
+
+    def connection(self):
+        return self.conn
+
+    def update(self, consinfo):
+        conn = sxp.child(consinfo, 'connected')
+        if conn:
+            self.conn = conn[1:]
+        else:
+            self.conn = None
+
+    def uri(self):
+        """Get the uri to use to connect to the console.
+        This will be a telnet: uri.
+
+        return uri
+        """
+        host = socket.gethostname()
+        return "telnet://%s:%s" % (host, self.console)
+
+class XendConsole:
+
+    dbpath = "console"
+
+    def  __init__(self):
+        self.db = XendDB.XendDB(self.dbpath)
+        self.console = {}
+        self.console_db = self.db.fetchall("")
+        if xroot.get_rebooted():
+            print 'XendConsole> rebooted: removing all console info'
+            self.rm_all()
+        eserver.subscribe('xend.domain.died', self.onDomainDied)
+        eserver.subscribe('xend.domain.destroy', self.onDomainDied)
+
+    def rm_all(self):
+        """Remove all console info. Used after reboot.
+        """
+        for (k, v) in self.console_db.items():
+            self._delete_console(k)
+
+    def refresh(self):
+        consoles = daemon.consoles()
+        cons = {}
+        for consinfo in consoles:
+            id = str(sxp.child_value(consinfo, 'id'))
+            cons[id] = consinfo
+            if id not in self.console:
+                self._new_console(consinfo)
+        for c in self.console.values():
+            consinfo = cons.get(c.id)
+            if consinfo:
+                c.update(consinfo)
+            else:
+                self._delete_console(c.id)
+
+    def onDomainDied(self, event, val):
+        dom = int(val)
+        #print 'XendConsole>onDomainDied', 'event', event, "dom=", dom
+        for c in self.consoles():
+            #print 'onDomainDied', "dom=", dom, "dom1=", c.dom1, "dom2=", c.dom2
+            if (c.dom1 == dom) or (c.dom2 == dom):
+                'XendConsole>onDomainDied', 'delete console dom=', dom
+                ctrl = daemon.get_domain_console(dom)
+                if ctrl:
+                    ctrl.close()
+                self._delete_console(c.id)
+
+    def sync(self):
+        self.db.saveall("", self.console_db)
+
+    def sync_console(self, id):
+        self.db.save(id, self.console_db[id])
+
+    def _new_console(self, consinfo):
+        # todo: xen needs a call to get current domain id.
+        dom1 = 0
+        port1 = sxp.child_value(consinfo, 'local_port')
+        dom2 = sxp.child_value(consinfo, 'domain')
+        port2 = sxp.child_value(consinfo, 'remote_port')
+        console = sxp.child_value(consinfo, 'console_port')
+        info = XendConsoleInfo(console, dom1, int(port1), int(dom2), int(port2))
+        info.update(consinfo)
+        self._add_console(info.id, info)
+        return info
+
+    def _add_console(self, id, info):
+        self.console[id] = info
+        self.console_db[id] = info.sxpr()
+        self.sync_console(id)
+
+    def _delete_console(self, id):
+        if id in self.console:
+            del self.console[id]
+        if id in self.console_db:
+            del self.console_db[id]
+            self.db.delete(id)
+
+    def console_ls(self):
+        self.refresh()
+        return self.console.keys()
+
+    def consoles(self):
+        self.refresh()
+        return self.console.values()
+    
+    def console_create(self, dom):
+        consinfo = daemon.console_create(dom)
+        info = self._new_console(consinfo)
+        return info
+    
+    def console_get(self, id):
+        self.refresh()
+        return self.console.get(id)
+
+    def console_delete(self, id):
+        self._delete_console(id)
+
+    def console_disconnect(self, id):
+        id = int(id)
+        daemon.console_disconnect(id)
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendConsole()
+    return inst
diff --git a/tools/xen/lib/xend/XendDB.py b/tools/xen/lib/xend/XendDB.py
new file mode 100644 (file)
index 0000000..6a27e65
--- /dev/null
@@ -0,0 +1,91 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+import os
+import os.path
+import errno
+import dircache
+import time
+
+import sxp
+import XendRoot
+xroot = XendRoot.instance()
+
+class XendDB:
+    """Persistence for Xend. Stores data in files and directories.
+    """
+
+    def __init__(self, path=None):
+        self.dbpath = xroot.get_dbroot()
+        if path:
+            self.dbpath = os.path.join(self.dbpath, path)
+        pass
+
+    def filepath(self, path):
+        return os.path.join(self.dbpath, path)
+        
+    def fetch(self, path):
+        fpath = self.filepath(path)
+        return self.fetchfile(fpath)
+
+    def fetchfile(self, fpath):
+        pin = sxp.Parser()
+        fin = file(fpath, "rb")
+        try:
+            while 1:
+                try:
+                    buf = fin.read(1024)
+                except IOError, ex:
+                    if ex.errno == errno.EINTR:
+                        continue
+                    else:
+                        raise
+                pin.input(buf)
+                if buf == '':
+                    pin.input_eof()
+                    break
+        finally:
+            fin.close()
+        return pin.get_val()
+
+    def save(self, path, sxpr):
+        fpath = self.filepath(path)
+        return self.savefile(fpath, sxpr)
+    
+    def savefile(self, fpath, sxpr):
+        fdir = os.path.dirname(fpath)
+        if not os.path.isdir(fdir):
+            os.makedirs(fdir)
+        fout = file(fpath, "wb+")
+        try:
+            t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
+            fout.write("# %s %s\n" % (fpath, t))
+            sxp.show(sxpr, out=fout)
+        finally:
+            fout.close()
+
+    def fetchall(self, path):
+        dpath = self.filepath(path)
+        d = {}
+        for k in dircache.listdir(dpath):
+            try:
+                v = self.fetchfile(os.path.join(dpath, k))
+                d[k] = v
+            except:
+                pass
+        return d
+
+    def saveall(self, path, d):
+        for (k, v) in d.items():
+            self.save(os.path.join(path, k), v)
+
+    def delete(self, path):
+        dpath = self.filepath(path)
+        os.unlink(dpath)
+
+    def ls(self, path):
+        dpath = self.filepath(path)
+        return dircache.listdir(dpath)
+            
+        
+
+        
diff --git a/tools/xen/lib/xend/XendDomain.py b/tools/xen/lib/xend/XendDomain.py
new file mode 100644 (file)
index 0000000..446b7f7
--- /dev/null
@@ -0,0 +1,366 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Handler for domain operations.
+ Nothing here is persistent (across reboots).
+ Needs to be persistent for one uptime.
+"""
+import sys
+
+from twisted.internet import defer
+
+import xen.ext.xc; xc = xen.ext.xc.new()
+import xenctl.ip
+
+import sxp
+import XendRoot
+xroot = XendRoot.instance()
+import XendDB
+import XendDomainInfo
+import XendConsole
+import EventServer
+
+from xen.xend.server import SrvDaemon
+xend = SrvDaemon.instance()
+
+eserver = EventServer.instance()
+
+__all__ = [ "XendDomain" ]
+        
+class XendDomain:
+    """Index of all domains. Singleton.
+    """
+    
+    dbpath = "domain"
+    domain = {}
+    
+    def __init__(self):
+        self.xconsole = XendConsole.instance()
+        # Table of domain info indexed by domain id.
+        self.db = XendDB.XendDB(self.dbpath)
+        #self.domain = {}
+        self.domain_db = self.db.fetchall("")
+        if xroot.get_rebooted():
+            print 'XendDomain> rebooted: removing all domain info'
+            self.rm_all()
+        eserver.subscribe('xend.virq', self.onVirq)
+        self.initial_refresh()
+
+    def onVirq(self, event, val):
+        print 'XendDomain> virq', val
+        self.reap()
+
+    def rm_all(self):
+        """Remove all domain info. Used after reboot.
+        """
+        for (k, v) in self.domain_db.items():
+            self._delete_domain(k, notify=0)
+            
+    def initial_refresh(self):
+        """Refresh initial domain info from domain_db.
+        """
+        print "initial_refresh>"
+        for d in self.domain_db.values(): print 'db dom=', d
+        domlist = xc.domain_getinfo()
+        for d in domlist: print 'xc dom=', d
+        doms = {}
+        for d in domlist:
+            domid = str(d['dom'])
+            doms[domid] = d
+        dlist = []
+        for config in self.domain_db.values():
+            domid = str(sxp.child_value(config, 'id'))
+            print "dom=", domid, "config=", config
+            if domid in doms:
+                print "dom=", domid, "new"
+                deferred = self._new_domain(config, doms[domid])
+                dlist.append(deferred)
+            else:
+                print "dom=", domid, "del"
+                self._delete_domain(domid)
+        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
+        def cbok(val):
+            #print "doms:"
+            #for d in self.domain.values(): print 'dom', d
+            self.refresh()
+            print "XendDomain>initial_refresh> doms:"
+            for d in self.domain.values(): print 'dom', d
+        deferred.addCallback(cbok)
+
+    def sync(self):
+        """Sync domain db to disk.
+        """
+        self.db.saveall("", self.domain_db)
+
+    def sync_domain(self, dom):
+        """Sync info for a domain to disk.
+
+        dom    domain id (string)
+        """
+        self.db.save(dom, self.domain_db[dom])
+
+    def close(self):
+        pass
+
+    def _new_domain(self, savedinfo, info):
+        """Create a domain entry from saved info.
+        """
+##         console = None
+##         kernel = None
+##         id = sxp.child_value(info, 'id')
+##         dom = int(id)
+##         name = sxp.child_value(info, 'name')
+##         memory = int(sxp.child_value(info, 'memory'))
+##         consoleinfo = sxp.child(info, 'console')
+##         if consoleinfo:
+##             consoleid = sxp.child_value(consoleinfo, 'id')
+##             console = self.xconsole.console_get(consoleid)
+##         if dom and console is None:
+##             # Try to connect a console.
+##             console = self.xconsole.console_create(dom)
+##         config = sxp.child(info, 'config')
+##         if config:
+##             image = sxp.child(info, 'image')
+##             if image:
+##                 image = sxp.child0(image)
+##                 kernel = sxp.child_value(image, 'kernel')
+##         dominfo = XendDomainInfo.XendDomainInfo(
+##             config, dom, name, memory, kernel, console)
+        config = sxp.child_value(savedinfo, 'config')
+        deferred = XendDomainInfo.vm_recreate(config, info)
+        def fn(dominfo):
+            self.domain[dominfo.id] = dominfo
+        deferred.addCallback(fn)
+        return deferred
+
+    def _add_domain(self, id, info, notify=1):
+        self.domain[id] = info
+        self.domain_db[id] = info.sxpr()
+        self.sync_domain(id)
+        if notify: eserver.inject('xend.domain.created', id)
+
+    def _delete_domain(self, id, notify=1):
+        if id in self.domain:
+            if notify: eserver.inject('xend.domain.died', id)
+            del self.domain[id]
+        if id in self.domain_db:
+            del self.domain_db[id]
+            self.db.delete(id)
+
+    def reap(self):
+        """Go through the domains looking for ones that have crashed or stopped.
+        Tidy them up.
+        """
+        print 'XendDomain>reap>'
+        domlist = xc.domain_getinfo()
+        casualties = []
+        for d in domlist:
+            #print 'dom', d
+            dead = 0
+            dead = dead or (d['crashed'] or d['shutdown'])
+            dead = dead or (d['dying'] and
+                            not(d['running'] or d['paused'] or d['blocked']))
+            if dead:
+                casualties.append(d)
+        for d in casualties:
+            id = str(d['dom'])
+            print 'XendDomain>reap> died id=', id, d
+            dominfo = self.domain.get(id)
+            if not dominfo: continue
+            dominfo.died()
+            self.domain_destroy(id, refresh=0)
+        print 'XendDomain>reap<'
+
+    def refresh(self):
+        """Refresh domain list from Xen.
+        """
+        domlist = xc.domain_getinfo()
+        # Index the domlist by id.
+        # Add entries for any domains we don't know about.
+        doms = {}
+        for d in domlist:
+            id = str(d['dom'])
+            doms[id] = d
+            if id not in self.domain:
+                config = None
+                #image = None
+                #newinfo = XendDomainInfo.XendDomainInfo(
+                #    config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d)
+                deferred = XendDomainInfo.vm_recreate(config, d)
+                def fn(dominfo):
+                    self._add_domain(dominfo.id, dominfo)
+                deferred.addCallback(fn)
+        # Remove entries for domains that no longer exist.
+        for d in self.domain.values():
+            dominfo = doms.get(d.id)
+            if dominfo:
+                d.update(dominfo)
+            else:
+                self._delete_domain(d.id)
+        self.reap()
+
+    def refresh_domain(self, id):
+        dom = int(id)
+        dominfo = xc.domain_getinfo(dom, 1)
+        if dominfo == [] or dominfo[0]['dom'] != dom:
+            try:
+                self._delete_domain(id)
+            except:
+                print 'refresh_domain: error'
+                raise
+                pass
+        else:
+            d = self.domain.get(id)
+            if d:
+                d.update(dominfo[0])
+
+    def domain_ls(self):
+        # List domains.
+        # Update info from kernel first.
+        self.refresh()
+        return self.domain.keys()
+
+    def domains(self):
+        self.refresh()
+        return self.domain.values()
+    
+    def domain_create(self, config):
+        # Create domain, log it.
+        deferred = XendDomainInfo.vm_create(config)
+        def fn(dominfo):
+            self._add_domain(dominfo.id, dominfo)
+            return dominfo
+        deferred.addCallback(fn)
+        return deferred
+    
+    def domain_get(self, id):
+        id = str(id)
+        self.refresh_domain(id)
+        return self.domain[id]
+    
+    def domain_unpause(self, id):
+        """(Re)start domain running.
+        """
+        dom = int(id)
+        eserver.inject('xend.domain.unpause', id)
+        return xc.domain_unpause(dom=dom)
+    
+    def domain_pause(self, id):
+        """Pause domain execution.
+        """
+        dom = int(id)
+        eserver.inject('xend.domain.pause', id)
+        return xc.domain_pause(dom=dom)
+    
+    def domain_shutdown(self, id, reason='poweroff'):
+        """Shutdown domain (nicely).
+        """
+        dom = int(id)
+        if dom <= 0:
+            return 0
+        eserver.inject('xend.domain.shutdown', [id, reason])
+        val = xend.domain_shutdown(dom, reason)
+        self.refresh()
+        return val
+    
+    def domain_destroy(self, id, refresh=1):
+        """Terminate domain immediately.
+        """
+        dom = int(id)
+        if dom <= 0:
+            return 0
+        eserver.inject('xend.domain.destroy', id)
+        val = xc.domain_destroy(dom=dom)
+        if refresh: self.refresh()
+        return val       
+
+    def domain_migrate(self, id, dst):
+        """Start domain migration.
+        """
+        # Need a cancel too?
+        pass
+    
+    def domain_save(self, id, dst, progress=0):
+        """Save domain state to file, destroy domain.
+        """
+        dom = int(id)
+        self.domain_pause(id)
+        eserver.inject('xend.domain.save', id)
+        rc = xc.linux_save(dom=dom, state_file=dst, progress=progress)
+        if rc == 0:
+            self.domain_destroy(id)
+        return rc
+    
+    def domain_restore(self, src, config, progress=0):
+        """Restore domain from file.
+        """
+        dominfo = XendDomainInfo.dom_restore(dom, config)
+        self._add_domain(dominfo.id, dominfo)
+        return dominfo
+    
+    #============================================================================
+    # Backward compatibility stuff from here on.
+
+    def domain_pincpu(self, dom, cpu):
+        dom = int(dom)
+        return xc.domain_pincpu(dom, cpu)
+
+    def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
+        dom = int(dom)
+        return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
+                                      warp=warp, warpl=warpl, warpu=warpu)
+
+    def domain_cpu_bvt_get(self, dom):
+        dom = int(dom)
+        return xc.bvtsched_domain_get(dom)
+    
+    def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
+        dom = int(dom)
+        return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
+
+    def domain_cpu_atropos_get(self, dom):
+        dom = int(dom)
+        return xc.atropos_domain_get(dom)
+
+    def domain_vif_ls(self, dom):
+        dominfo = self.domain_get(dom)
+        if not dominfo: return None
+        devs = dominfo.get_devices('vif')
+        return range(0, len(devs))
+
+    def domain_vif_get(self, dom, vif):
+        dominfo = self.domain_get(dom)
+        if not dominfo: return None
+        return dominfo.get_device_by_index(vif)
+
+    def domain_vif_ip_add(self, dom, vif, ip):
+        dom = int(dom)
+        return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
+
+    def domain_vbd_ls(self, dom):
+        dominfo = self.domain_get(dom)
+        if not dominfo: return []
+        devs = dominfo.get_devices('vbd')
+        return [ sxp.child_value(v, 'dev') for v in devs ]
+
+    def domain_vbd_get(self, dom, vbd):
+        dominfo = self.domain_get(dom)
+        if not dominfo: return None
+        devs = dominfo.get_devices('vbd')
+        for v in devs:
+            if sxp.child_value(v, 'dev') == vbd:
+                return v
+        return None
+
+    def domain_shadow_control(self, dom, op):
+        dom = int(dom)
+        return xc.shadow_control(dom, op)
+
+    #============================================================================
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendDomain()
+    return inst
diff --git a/tools/xen/lib/xend/XendDomainConfig.py b/tools/xen/lib/xend/XendDomainConfig.py
new file mode 100644 (file)
index 0000000..35db31f
--- /dev/null
@@ -0,0 +1,44 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Handler for persistent domain configs.
+
+"""
+
+import sxp
+import XendDB
+import XendDomain
+
+__all__ = [ "XendDomainConfig" ]
+
+class XendDomainConfig:
+
+    dbpath = 'config'
+
+    def __init__(self):
+        self.db = XendDB.XendDB(self.dbpath)
+
+    def domain_config_ls(self, path):
+        return self.db.ls(path)
+
+    def domain_config_create(self, path, sxpr):
+        self.db.save(path, sxpr)
+        pass
+
+    def domain_config_delete(self, path):
+        self.db.delete(path)
+
+    def domain_config_instance(self, path):
+        """Create a domain from a config.
+        """
+        config = self.db.fetch(path)
+        xd = XendDomain.instance()
+        newdom = xd.domain_create(config)
+        return newdom
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendDomainConfig()
+    return inst
diff --git a/tools/xen/lib/xend/XendDomainInfo.py b/tools/xen/lib/xend/XendDomainInfo.py
new file mode 100644 (file)
index 0000000..964285e
--- /dev/null
@@ -0,0 +1,911 @@
+#!/usr/bin/python
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Representation of a single domain.
+Includes support for domain construction, using
+open-ended configurations.
+
+Author: Mike Wray <mike.wray@hpl.hp.com>
+
+"""
+
+import string
+import re
+import sys
+import os
+
+from twisted.internet import defer
+
+import xen.ext.xc; xc = xen.ext.xc.new()
+import xenctl.ip
+
+import sxp
+
+import XendConsole
+xendConsole = XendConsole.instance()
+
+import XendBridge
+
+import server.SrvDaemon
+xend = server.SrvDaemon.instance()
+
+SIF_BLK_BE_DOMAIN = (1<<4)
+SIF_NET_BE_DOMAIN = (1<<5)
+
+def readlines(fd):
+    """Version of readlines safe against EINTR.
+    """
+    import errno
+    
+    lines = []
+    while 1:
+        try:
+            line = fd.readline()
+        except IOError, ex:
+            if ex.errno == errno.EINTR:
+                continue
+            else:
+                raise
+        if line == '': break
+        lines.append(line)
+    return lines
+
+class VmError(ValueError):
+    """Vm construction error."""
+
+    def __init__(self, value):
+        self.value = value
+
+    def __str__(self):
+        return self.value
+
+
+def blkdev_name_to_number(name):
+    """Take the given textual block-device name (e.g., '/dev/sda1',
+    'hda') and return the device number used by the OS. """
+
+    if not re.match( '/dev/', name ):
+        name = '/dev/' + name
+        
+    return os.stat(name).st_rdev
+
+def lookup_raw_partn(partition):
+    """Take the given block-device name (e.g., '/dev/sda1', 'hda')
+    and return a dictionary { device, start_sector,
+    nr_sectors, type }
+        device:       Device number of the given partition
+        start_sector: Index of first sector of the partition
+        nr_sectors:   Number of sectors comprising this partition
+        type:         'Disk' or identifying name for partition type
+    """
+
+    if not re.match( '/dev/', partition ):
+        partition = '/dev/' + partition
+
+    drive = re.split( '[0-9]', partition )[0]
+
+    if drive == partition:
+        fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
+        line = readline(fd)
+        if line:
+            return [ { 'device' : blkdev_name_to_number(drive),
+                       'start_sector' : long(0),
+                       'nr_sectors' : long(line) * 2,
+                       'type' : 'Disk' } ]
+        return None
+
+    # determine position on disk
+    fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
+
+    #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
+    lines = readlines(fd)
+    for line in lines:
+        m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
+                       'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
+        if m:
+            return [ { 'device' : blkdev_name_to_number(drive),
+                       'start_sector' : long(m.group(1)),
+                       'nr_sectors' : long(m.group(2)),
+                       'type' : m.group(3) } ]
+    
+    return None
+
+def lookup_disk_uname(uname):
+    """Lookup a list of segments for a physical device.
+    uname [string]:  name of the device in the format \'phy:dev\' for a physical device
+    returns [list of dicts]: list of extents that make up the named device
+    """
+    ( type, d_name ) = string.split( uname, ':' )
+
+    if type == "phy":
+        segments = lookup_raw_partn( d_name )
+    else:
+        segments = None
+    return segments
+
+def make_disk(dom, uname, dev, mode, recreate=0):
+    """Create a virtual disk device for a domain.
+
+    @returns Deferred
+    """
+    segments = lookup_disk_uname(uname)
+    if not segments:
+        raise VmError("vbd: Segments not found: uname=%s" % uname)
+    if len(segments) > 1:
+        raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname)
+    segment = segments[0]
+    vdev = blkdev_name_to_number(dev)
+    ctrl = xend.blkif_create(dom, recreate=recreate)
+    
+    def fn(ctrl):
+        return xend.blkif_dev_create(dom, vdev, mode, segment, recreate=recreate)
+    ctrl.addCallback(fn)
+    return ctrl
+        
+def make_vif(dom, vif, vmac, recreate=0):
+    """Create a virtual network device for a domain.
+
+    
+    @returns Deferred
+    """
+    xend.netif_create(dom, recreate=recreate)
+    d = xend.netif_dev_create(dom, vif, vmac, recreate=recreate)
+    return d
+
+def vif_up(iplist):
+    """send an unsolicited ARP reply for all non link-local IP addresses.
+
+    iplist IP addresses
+    """
+
+    IP_NONLOCAL_BIND = '/proc/sys/net/ipv4/ip_nonlocal_bind'
+    
+    def get_ip_nonlocal_bind():
+        return int(open(IP_NONLOCAL_BIND, 'r').read()[0])
+
+    def set_ip_nonlocal_bind(v):
+        print >> open(IP_NONLOCAL_BIND, 'w'), str(v)
+
+    def link_local(ip):
+        return xenctl.ip.check_subnet(ip, '169.254.0.0', '255.255.0.0')
+
+    def arping(ip, gw):
+        cmd = '/usr/sbin/arping -A -b -I eth0 -c 1 -s %s %s' % (ip, gw)
+        print cmd
+        os.system(cmd)
+        
+    gateway = xenctl.ip.get_current_ipgw() or '255.255.255.255'
+    nlb = get_ip_nonlocal_bind()
+    if not nlb: set_ip_nonlocal_bind(1)
+    try:
+        for ip in iplist:
+            if not link_local(ip):
+                arping(ip, gateway)
+    finally:
+        if not nlb: set_ip_nonlocal_bind(0)
+
+config_handlers = {}
+
+def add_config_handler(name, h):
+    """Add a handler for a config field.
+
+    name     field name
+    h        handler: fn(vm, config, field, index)
+    """
+    config_handlers[name] = h
+
+def get_config_handler(name):
+    """Get a handler for a config field.
+
+    returns handler or None
+    """
+    return config_handlers.get(name)
+
+"""Table of handlers for virtual machine images.
+Indexed by image type.
+"""
+image_handlers = {}
+
+def add_image_handler(name, h):
+    """Add a handler for an image type
+    name     image type
+    h        handler: fn(config, name, memory, image)
+    """
+    image_handlers[name] = h
+
+def get_image_handler(name):
+    """Get the handler for an image type.
+    name     image type
+
+    returns handler or None
+    """
+    return image_handlers.get(name)
+
+"""Table of handlers for devices.
+Indexed by device type.
+"""
+device_handlers = {}
+
+def add_device_handler(name, h):
+    """Add a handler for a device type.
+
+    name      device type
+    h         handler: fn(vm, dev)
+    """
+    device_handlers[name] = h
+
+def get_device_handler(name):
+    """Get the handler for a device type.
+
+    name      device type
+
+    returns handler or None
+    """
+    return device_handlers.get(name)
+
+def vm_create(config):
+    """Create a VM from a configuration.
+    If a vm has been partially created and there is an error it
+    is destroyed.
+
+    config    configuration
+
+    returns Deferred
+    raises VmError for invalid configuration
+    """
+    print 'vm_create>'
+    vm = XendDomainInfo()
+    return vm.construct(config)
+
+def vm_recreate(config, info):
+    """Create the VM object for an existing domain.
+    """
+    vm = XendDomainInfo()
+    vm.recreate = 1
+    vm.setdom(info['dom'])
+    vm.name = info['name']
+    vm.memory = info['mem_kb']/1024
+    if config:
+        d = vm.construct(config)
+    else:
+        d = defer.Deferred()
+        d.callback(vm)
+    return d
+
+def vm_restore(src, config, progress=0):
+    """Restore a VM from a disk image.
+
+    src      saved state to restore
+    config   configuration
+    progress progress reporting flag
+    returns  deferred
+    raises   VmError for invalid configuration
+    """
+    vm = XendDomainInfo()
+    vm.config = config
+    ostype = "linux" #todo set from config
+    restorefn = getattr(xc, "%s_restore" % ostype)
+    dom = restorefn(state_file=src, progress=progress)
+    if dom < 0:
+        raise VMError('restore failed')
+    deferred = vm.dom_configure(dom)
+    def vifs_cb(val, vm):
+        vif_up(vm.ipaddrs)
+    deferred.addCallback(vifs_cb, vm)
+    return deferred
+    
+def dom_get(dom):
+    domlist = xc.domain_getinfo(dom=dom)
+    if domlist and dom == domlist[0]['dom']:
+        return domlist[0]
+    return None
+    
+
+def append_deferred(dlist, v):
+    if isinstance(v, defer.Deferred):
+        dlist.append(v)
+
+def _vm_configure1(val, vm):
+    d = vm.create_devices()
+    print '_vm_configure1> made devices...'
+    def cbok(x):
+        print '_vm_configure1> cbok', x
+        return x
+    d.addCallback(cbok)
+    d.addCallback(_vm_configure2, vm)
+    print '_vm_configure1<'
+    return d
+
+def _vm_configure2(val, vm):
+    print '>callback _vm_configure2...'
+    d = vm.configure_fields()
+    def cbok(results):
+        print '_vm_configure2> cbok', results
+        return vm
+    def cberr(err):
+        print '_vm_configure2> cberr', err
+        vm.destroy()
+        return err
+    d.addCallback(cbok)
+    d.addErrback(cberr)
+    print '<_vm_configure2'
+    return d
+
+class XendDomainInfo:
+    """Virtual machine object."""
+
+    def __init__(self):
+        self.recreate = 0
+        self.config = None
+        self.id = None
+        self.dom = None
+        self.name = None
+        self.memory = None
+        self.image = None
+        self.ramdisk = None
+        self.cmdline = None
+        self.console = None
+        self.devices = {}
+        self.configs = []
+        self.info = None
+        self.ipaddrs = []
+        self.blkif_backend = 0
+        self.netif_backend = 0
+        #todo: state: running, suspended
+        self.state = 'running'
+        #todo: set to migrate info if migrating
+        self.migrate = None
+
+    def setdom(self, dom):
+        self.dom = int(dom)
+        self.id = str(dom)
+        
+    def update(self, info):
+        """Update with  info from xc.domain_getinfo().
+        """
+        self.info = info
+        self.memory = self.info['mem_kb'] / 1024
+
+    def __str__(self):
+        s = "domain"
+        s += " id=" + self.id
+        s += " name=" + self.name
+        s += " memory=" + str(self.memory)
+        if self.console:
+            s += " console=" + self.console.id
+        if self.image:
+            s += " image=" + self.image
+        s += ""
+        return s
+
+    __repr__ = __str__
+
+    def sxpr(self):
+        sxpr = ['domain',
+                ['id', self.id],
+                ['name', self.name],
+                ['memory', self.memory] ]
+        if self.info:
+            run   = (self.info['running'] and 'r') or '-'
+            block = (self.info['blocked'] and 'b') or '-'
+            stop  = (self.info['paused']  and 'p') or '-'
+            susp  = (self.info['shutdown'] and 's') or '-'
+            crash = (self.info['crashed'] and 'c') or '-'
+            state = run + block + stop + susp + crash
+            sxpr.append(['state', state])
+            if self.info['shutdown']:
+                reasons = ["poweroff", "reboot", "suspend"]
+                reason = reasons[self.info['shutdown_reason']]
+                sxpr.append(['shutdown_reason', reason])
+            sxpr.append(['cpu', self.info['cpu']])
+            sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
+        if self.console:
+            sxpr.append(self.console.sxpr())
+        if self.config:
+            sxpr.append(['config', self.config])
+        return sxpr
+
+    def construct(self, config):
+        # todo - add support for scheduling params?
+        self.config = config
+        try:
+            self.name = sxp.child_value(config, 'name')
+            self.memory = int(sxp.child_value(config, 'memory', '128'))
+            self.configure_backends()
+            image = sxp.child_value(config, 'image')
+            image_name = sxp.name(image)
+            image_handler = get_image_handler(image_name)
+            if image_handler is None:
+                raise VmError('unknown image type: ' + image_name)
+            image_handler(self, image)
+            deferred = self.configure()
+        except StandardError, ex:
+            # Catch errors, cleanup and re-raise.
+            self.destroy()
+            raise
+        def cbok(x):
+            print 'vm_create> cbok', x
+            return x
+        deferred.addCallback(cbok)
+        print 'vm_create<'
+        return deferred
+
+    def config_devices(self, name):
+        """Get a list of the 'device' nodes of a given type from the config.
+
+        name   device type
+        return list of device configs
+        """
+        devices = []
+        for d in sxp.children(self.config, 'device'):
+            dev = sxp.child0(d)
+            if dev is None: continue
+            if name == sxp.name(dev):
+                devices.append(dev)
+        return devices
+
+    def add_device(self, type, dev):
+        """Add a device to a virtual machine.
+
+        dev      device to add
+        """
+        dl = self.devices.get(type, [])
+        dl.append(dev)
+        self.devices[type] = dl
+
+    def get_devices(self, type):
+        val = self.devices.get(type, [])
+        return val
+
+    def get_device_by_id(self, type, id):
+        """Get the device with the given id.
+
+        id       device id
+
+        returns  device or None
+        """
+        dl = self.get_devices(type)
+        for d in dl:
+            if d.getprop('id') == id:
+                return d
+        return None
+
+    def get_device_by_index(self, type, idx):
+        """Get the device with the given index.
+
+        idx       device index
+
+        returns  device or None
+        """
+        dl = self.get_devices(type)
+        if 0 <= idx < len(dl):
+            return dl[idx]
+        else:
+            return None
+
+    def add_config(self, val):
+        """Add configuration data to a virtual machine.
+
+        val      data to add
+        """
+        self.configs.append(val)
+
+    def destroy(self):
+        if self.dom <= 0:
+            return 0
+        return xc.domain_destroy(dom=self.dom)
+
+    def died(self):
+        print 'died>', self.dom
+        self.release_devices()
+
+    def release_devices(self):
+        print 'release_devices>', self.dom
+        self.release_vifs()
+        self.release_vbds()
+        self.devices = {}
+
+    def release_vifs(self):
+        print 'release_vifs>', self.dom
+        if self.dom is None: return
+        ctrl = xend.netif_get(self.dom)
+        if ctrl:
+            ctrl.destroy()
+
+    def release_vbds(self):
+        print 'release_vbds>', self.dom
+        if self.dom is None: return
+        ctrl = xend.blkif_get(self.dom)
+        if ctrl:
+            ctrl.destroy()
+
+    def show(self):
+        """Print virtual machine info.
+        """
+        print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory)
+        print "image:"
+        sxp.show(self.image)
+        print
+        for dl in self.devices:
+            for dev in dl:
+                print "device:"
+                sxp.show(dev)
+                print
+        for val in self.configs:
+            print "config:"
+            sxp.show(val)
+            print
+        print "]"
+
+    def init_domain(self):
+        """Initialize the domain memory.
+        """
+        if self.recreate: return
+        memory = self.memory
+        name = self.name
+        cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
+        print 'init_domain>', memory, name, cpu
+        dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
+        if dom <= 0:
+            raise VmError('Creating domain failed: name=%s memory=%d'
+                          % (name, memory))
+        self.setdom(dom)
+
+    def build_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
+        """Build the domain boot image.
+        """
+        if self.recreate: return
+        if len(cmdline) >= 256:
+            print 'Warning: kernel cmdline too long'
+        dom = self.dom
+        buildfn = getattr(xc, '%s_build' % ostype)
+        print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk
+        flags = 0
+        if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
+        if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
+        err = buildfn(dom            = dom,
+                      image          = kernel,
+                      control_evtchn = self.console.port2,
+                      cmdline        = cmdline,
+                      ramdisk        = ramdisk,
+                      flags          = flags)
+        if err != 0:
+            raise VmError('Building domain failed: type=%s dom=%d err=%d'
+                          % (ostype, dom, err))
+
+    def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
+        """Create a domain. Builds the image but does not configure it.
+
+        ostype  OS type
+        kernel  kernel image
+        ramdisk kernel ramdisk
+        cmdline kernel commandline
+        vifs_n  number of network interfaces
+        """
+        print 'create_domain>', ostype, kernel
+        if not self.recreate:
+            if not os.path.isfile(kernel):
+                raise VmError('Kernel image does not exist: %s' % kernel)
+            if ramdisk and not os.path.isfile(ramdisk):
+                raise VMError('Kernel ramdisk does not exist: %s' % ramdisk)
+        print 'create-domain> init_domain...'
+        self.init_domain()
+        print 'create_domain>', 'dom=', self.dom
+        self.console = xendConsole.console_create(self.dom)
+        self.build_domain(ostype, kernel, ramdisk, cmdline, vifs_n)
+        self.image = kernel
+        self.ramdisk = ramdisk
+        self.cmdline = cmdline
+
+    def create_devices(self):
+        """Create the devices for a vm.
+
+        returns Deferred
+        raises VmError for invalid devices
+        """
+        print '>create_devices'
+        dlist = []
+        devices = sxp.children(self.config, 'device')
+        index = {}
+        for d in devices:
+            dev = sxp.child0(d)
+            if dev is None:
+                raise VmError('invalid device')
+            dev_name = sxp.name(dev)
+            dev_index = index.get(dev_name, 0)
+            dev_handler = get_device_handler(dev_name)
+            if dev_handler is None:
+                raise VmError('unknown device type: ' + dev_name)
+            v = dev_handler(self, dev, dev_index)
+            append_deferred(dlist, v)
+            index[dev_name] = dev_index + 1
+        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
+        print '<create_devices'
+        return deferred
+
+    def configure_backends(self):
+        """Set configuration flags if the vm is a backend for netif of blkif.
+        """
+        for c in sxp.children(self.config, 'backend'):
+            name = sxp.name(c)
+            if name == 'blkif':
+                self.blkif_backend = 1
+            elif name == 'netif':
+                self.netif_backend = 1
+            else:
+                raise VmError('invalid backend type:' + str(name))
+
+    def create_backends(self):
+        """Setup the netif and blkif backends.
+        """
+        if self.blkif_backend:
+            xend.blkif_set_control_domain(self.dom, recreate=self.recreate)
+        if self.netif_backend:
+            xend.netif_set_control_domain(self.dom, recreate=self.recreate)
+            
+    def configure(self):
+        """Configure a vm.
+
+        vm         virtual machine
+        config     configuration
+
+        returns Deferred - calls callback with vm
+        """
+        if self.blkif_backend:
+            d = defer.Deferred()
+            d.callback(1)
+        else:
+            d = xend.blkif_create(self.dom, recreate=self.recreate)
+        d.addCallback(_vm_configure1, self)
+        return d
+
+    def dom_configure(self, dom):
+        """Configure a domain.
+
+        dom    domain id
+        returns deferred
+        """
+        d = dom_get(dom)
+        if not d:
+            raise VMError("Domain not found: %d" % dom)
+        try:
+            self.setdom(dom)
+            self.name = d['name']
+            self.memory = d['memory']/1024
+            deferred = self.configure()
+        except StandardError, ex:
+            self.destroy()
+            raise
+        return deferred
+
+    def configure_fields(self):
+        dlist = []
+        index = {}
+        for field in sxp.children(self.config):
+            field_name = sxp.name(field)
+            field_index = index.get(field_name, 0)
+            field_handler = get_config_handler(field_name)
+            # Ignore unknown fields. Warn?
+            if field_handler:
+                v = field_handler(self, self.config, field, field_index)
+                append_deferred(dlist, v)
+            index[field_name] = field_index + 1
+        d = defer.DeferredList(dlist, fireOnOneErrback=1)
+        return d
+
+
+def vm_image_linux(vm, image):
+    """Create a VM for a linux image.
+
+    name      vm name
+    memory    vm memory
+    image     image config
+
+    returns vm
+    """
+    kernel = sxp.child_value(image, "kernel")
+    cmdline = ""
+    ip = sxp.child_value(image, "ip", "dhcp")
+    if ip:
+        cmdline += " ip=" + ip
+    root = sxp.child_value(image, "root")
+    if root:
+        cmdline += " root=" + root
+    args = sxp.child_value(image, "args")
+    if args:
+        cmdline += " " + args
+    ramdisk = sxp.child_value(image, "ramdisk", '')
+    vifs = vm.config_devices("vif")
+    vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs))
+    return vm
+
+def vm_image_netbsd(vm, image):
+    """Create a VM for a bsd image.
+
+    name      vm name
+    memory    vm memory
+    image     image config
+
+    returns vm
+    """
+    #todo: Same as for linux. Is that right? If so can unify them.
+    kernel = sxp.child_value(image, "kernel")
+    cmdline = ""
+    ip = sxp.child_value(image, "ip", "dhcp")
+    if ip:
+        cmdline += "ip=" + ip
+    root = sxp.child_value(image, "root")
+    if root:
+        cmdline += "root=" + root
+    args = sxp.child_value(image, "args")
+    if args:
+        cmdline += " " + args
+    ramdisk = sxp.child_value(image, "ramdisk")
+    vifs = vm.config_devices("vif")
+    vm.create_domain("netbsd", kernel, ramdisk, cmdline, len(vifs))
+    return vm
+
+
+def vm_dev_vif(vm, val, index):
+    """Create a virtual network interface (vif).
+
+    vm        virtual machine
+    val       vif config
+    index     vif index
+    """
+    if vm.netif_backend:
+        raise VmError('vif: vif in netif backend domain')
+    vif = index #todo
+    vmac = sxp.child_value(val, "mac")
+    defer = make_vif(vm.dom, vif, vmac, vm.recreate)
+    def fn(id):
+        dev = xend.netif_dev(vm.dom, vif)
+        devid = sxp.attribute(val, 'id')
+        if devid:
+            dev.setprop('id', devid)
+        bridge = sxp.child_value(val, "bridge")
+        dev.bridge_add(bridge)
+        vm.add_device('vif', dev)
+        print 'vm_dev_vif> created', dev
+        return id
+    defer.addCallback(fn)
+    return defer
+
+def vm_dev_vbd(vm, val, index):
+    """Create a virtual block device (vbd).
+
+    vm        virtual machine
+    val       vbd config
+    index     vbd index
+    """
+    if vm.blkif_backend:
+        raise VmError('vbd: vbd in blkif backend domain')
+    vdev = index
+    uname = sxp.child_value(val, 'uname')
+    if not uname:
+        raise VMError('vbd: Missing uname')
+    dev = sxp.child_value(val, 'dev')
+    if not dev:
+        raise VMError('vbd: Missing dev')
+    mode = sxp.child_value(val, 'mode', 'r')
+    defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
+    def fn(vbd):
+        dev = xend.blkif_dev(vm.dom, vdev)
+        vm.add_device('vbd', dev)
+        return vbd
+    defer.addCallback(fn)
+    return defer
+
+def parse_pci(val):
+    if isinstance(val, StringType):
+        radix = 10
+        if val.startswith('0x') or val.startswith('0X'):
+            radix = 16
+        v = int(val, radix)
+    else:
+        v = val
+    return v
+
+def vm_dev_pci(vm, val, index):
+    bus = sxp.child_value(val, 'bus')
+    if not bus:
+        raise VMError('pci: Missing bus')
+    dev = sxp.child_value(val, 'dev')
+    if not dev:
+        raise VMError('pci: Missing dev')
+    func = sxp.child_value(val, 'func')
+    if not func:
+        raise VMError('pci: Missing func')
+    try:
+        bus = parse_pci(bus)
+        dev = parse_pci(dev)
+        func = parse_pci(func)
+    except:
+        raise VMError('pci: invalid parameter')
+    rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev,
+                                      func=func, enable=1)
+    if rc < 0:
+        #todo non-fatal
+        raise VMError('pci: Failed to configure device: bus=%s dev=%s func=%s' %
+                      (bus, dev, func))
+    return rc
+    
+
+def vm_field_vfr(vm, config, val, index):
+    """Handle a vfr field in a config.
+
+    vm        virtual machine
+    config    vm config
+    val       vfr field
+    """
+    # Get the rules and add them.
+    # (vfr (vif (id foo) (ip x.x.x.x)) ... ) 
+    list = sxp.children(val, 'vif')
+    ipaddrs = []
+    for v in list:
+        id = sxp.child_value(v, 'id')
+        if id is None:
+            raise VmError('vfr: missing vif id')
+        id = int(id)
+        dev = vm.get_device_by_index('vif', id)
+        if not dev:
+            raise VmError('vfr: invalid vif id %d' % id)
+        vif = sxp.child_value(dev, 'vif')
+        ip = sxp.child_value(v, 'ip')
+        if not ip:
+            raise VmError('vfr: missing ip address')
+        ipaddrs.append(ip);
+        #Don't do this in new i/o model.
+        #print 'vm_field_vfr> add rule', 'dom=', vm.dom, 'vif=', vif, 'ip=', ip
+        #xenctl.ip.setup_vfr_rules_for_vif(vm.dom, vif, ip)
+    vm.ipaddrs = ipaddrs
+
+def vnet_bridge(vnet, vmac, dom, idx):
+    """Add the device for the vif to the bridge for its vnet.
+    """
+    vif = "vif%d.%d" % (dom, idx)
+    try:
+        cmd = "(vif.conn (vif %s) (vnet %s) (vmac %s))" % (vif, vnet, vmac)
+        print "*** vnet_bridge>", cmd
+        out = file("/proc/vnet/policy", "wb")
+        out.write(cmd)
+        err = out.close()
+        print "vnet_bridge>", "err=", err
+    except IOError, ex:
+        print "vnet_bridge>", ex
+    
+def vm_field_vnet(vm, config, val, index):
+    """Handle a vnet field in a config.
+
+    vm        virtual machine
+    config    vm config
+    val       vnet field
+    index     index
+    """
+    # Get the vif children. For each vif look up the vif device
+    # with the given id and configure its vnet.
+    # (vnet (vif (id foo) (vnet 2) (mac x:x:x:x:x:x)) ... )
+    vif_vnets = sxp.children(val, 'vif')
+    for v in vif_vnets:
+        id = sxp.child_value(v, 'id')
+        if id is None:
+            raise VmError('vnet: missing vif id')
+        dev = vm.get_device_by_id('vif', id)
+        #vnet = sxp.child_value(v, 'vnet', 1)
+        #mac = sxp.child_value(dev, 'mac')
+        #vif = sxp.child_value(dev, 'vif')
+        #vnet_bridge(vnet, mac, vm.dom, 0)
+        #vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
+
+# Register image handlers for linux and bsd.
+add_image_handler('linux',  vm_image_linux)
+add_image_handler('netbsd', vm_image_netbsd)
+
+# Register device handlers for vifs and vbds.
+add_device_handler('vif',  vm_dev_vif)
+add_device_handler('vbd',  vm_dev_vbd)
+add_device_handler('pci',  vm_dev_pci)
+
+# Register config handlers for vfr and vnet.
+add_config_handler('vfr',  vm_field_vfr)
+add_config_handler('vnet', vm_field_vnet)
diff --git a/tools/xen/lib/xend/XendMigrate.py b/tools/xen/lib/xend/XendMigrate.py
new file mode 100644 (file)
index 0000000..1580ba8
--- /dev/null
@@ -0,0 +1,103 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+import sys
+import socket
+
+import sxp
+import XendDB
+import EventServer; eserver = EventServer.instance()
+
+class XendMigrateInfo:
+
+    # states: begin, active, failed, succeeded?
+
+    def __init__(self, id, dom, dst):
+        self.id = id
+        self.state = 'begin'
+        self.src_host = socket.gethostname()
+        self.src_dom = dom
+        self.dst_host = dst
+        self.dst_dom = None
+        
+    def set_state(self, state):
+        self.state = state
+
+    def get_state(self):
+        return self.state
+
+    def sxpr(self):
+        sxpr = ['migrate', ['id', self.id], ['state', self.state] ]
+        sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ]
+        sxpr.append(sxpr_src)
+        sxpr_dst = ['dst', ['host', self.dst] ]
+        if self.dst_dom:
+            sxpr_dst.append(['domain', self.dst_dom])
+        sxpr.append(sxpr_dst)
+        return sxpr
+    
+
+class XendMigrate:
+    # Represents migration in progress.
+    # Use log for indications of begin/end/errors?
+    # Need logging of: domain create/halt, migrate begin/end/fail
+    # Log via event server?
+
+    dbpath = "migrate"
+    
+    def __init__(self):
+        self.db = XendDB.XendDB(self.dbpath)
+        self.migrate = {}
+        self.migrate_db = self.db.fetchall("")
+        self.id = 0
+
+    def nextid(self):
+        self.id += 1
+        return "%d" % self.id
+
+    def sync(self):
+        self.db.saveall("", self.migrate_db)
+
+    def sync_migrate(self, id):
+        self.db.save(id, self.migrate_db[id])
+
+    def close(self):
+        pass
+
+    def _add_migrate(self, id, info):
+        self.migrate[id] = info
+        self.migrate_db[id] = info.sxpr()
+        self.sync_migrate(id)
+        #eserver.inject('xend.migrate.begin', info.sxpr())
+
+    def _delete_migrate(self, id):
+        #eserver.inject('xend.migrate.end', id)
+        del self.migrate[id]
+        del self.migrate_db[id]
+        self.db.delete(id)
+
+    def migrate_ls(self):
+        return self.migrate.keys()
+
+    def migrates(self):
+        return self.migrate.values()
+
+    def migrate_get(self, id):
+        return self.migrate.get(id)
+    
+    def migrate_begin(self, dom, dst):
+        # Check dom for existence, not migrating already.
+        # Create migrate info, tell xend to migrate it?
+        # - or fork migrate command ourselves?
+        # Subscribe to migrate notifications (for updating).
+        id = self.nextid()
+        info = XenMigrateInfo(id, dom, dst)
+        self._add_migrate(id, info)
+        return id
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendMigrate()
+    return inst
diff --git a/tools/xen/lib/xend/XendNode.py b/tools/xen/lib/xend/XendNode.py
new file mode 100644 (file)
index 0000000..7221785
--- /dev/null
@@ -0,0 +1,71 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Handler for node operations.
+ Has some persistent state:
+ - logs
+ - notification urls
+
+"""
+
+import os
+import xen.ext.xc
+
+class XendNode:
+
+    def __init__(self):
+        self.xc = xen.ext.xc.new()
+
+    def shutdown(self):
+        return 0
+
+    def reboot(self):
+        return 0
+
+    def notify(self, uri):
+        return 0
+    
+    def cpu_bvt_slice_set(self, slice):
+        ret = 0
+        #ret = self.xc.bvtsched_global_set(ctx_allow=slice)
+        return ret
+
+    def cpu_bvt_slice_get(self, slice):
+        ret = 0
+        #ret = self.xc.bvtsched_global_get()
+        return ret
+    
+    def cpu_rrobin_slice_set(self, slice):
+        ret = 0
+        #ret = self.xc.rrobin_global_set(slice)
+        return ret
+
+    def info(self):
+        return self.nodeinfo() + self.physinfo()
+
+    def nodeinfo(self):
+        (sys, host, rel, ver, mch) = os.uname()
+        return [['system',  sys],
+                ['host',    host],
+                ['release', rel],
+                ['version', ver],
+                ['machine', mch]]
+
+    def physinfo(self):
+        pinfo = self.xc.physinfo()
+        info = [['cores', pinfo['cores']],
+                ['hyperthreads_per_core', pinfo['ht_per_core']],
+                ['cpu_mhz', pinfo['cpu_khz']/1000],
+                ['memory', pinfo['total_pages']/256],
+                ['free_memory', pinfo['free_pages']/256]]
+        return info
+        
+        
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendNode()
+    return inst
+
diff --git a/tools/xen/lib/xend/XendRoot.py b/tools/xen/lib/xend/XendRoot.py
new file mode 100644 (file)
index 0000000..665f5df
--- /dev/null
@@ -0,0 +1,156 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Xend root class.
+Creates the event server and handles configuration.
+"""
+
+import os
+import os.path
+import sys
+import EventServer
+
+# Initial create of the event server.
+eserver = EventServer.instance()
+
+import sxp
+
+def reboots():
+    """Get a list of system reboots from wtmp.
+    """
+    out = os.popen('/usr/bin/last reboot', 'r')
+    list = [ x.strip() for x in out if x.startswith('reboot') ]
+    return list
+
+def last_reboot():
+    """Get the last known system reboot.
+    """
+    l = reboots()
+    return (l and l[-1]) or None
+
+class XendRoot:
+    """Root of the management classes."""
+
+    lastboot_default = "/var/xen/lastboot"
+
+    """Default path to the root of the database."""
+    dbroot_default = "/var/xen/xend-db"
+
+    """Default path to the config file."""
+    config_default = "/etc/xen/xend-config.sxp"
+
+    """Environment variable used to override config_default."""
+    config_var     = "XEND_CONFIG"
+
+    def __init__(self):
+        self.rebooted = 0
+        self.last_reboot = None
+        self.dbroot = None
+        self.config_path = None
+        self.config = None
+        self.configure()
+        self.check_lastboot()
+        eserver.subscribe('xend.*', self.event_handler)
+        #eserver.subscribe('xend.domain.created', self.event_handler)
+        #eserver.subscribe('xend.domain.died', self.event_handler)
+
+    def start(self):
+        eserver.inject('xend.start', self.rebooted)
+
+    def event_handler(self, event, val):
+        print >> sys.stderr, "EVENT>", event, val
+
+    def read_lastboot(self):
+        try:
+            val = file(self.lastboot, 'rb').readlines()[0]
+        except StandardError, ex:
+            print 'warning: Error reading', self.lastboot, ex
+            val = None
+        return val
+
+    def write_lastboot(self, val):
+        if not val: return
+        try:
+            fdir = os.path.dirname(self.lastboot)
+            if not os.path.isdir(fdir):
+                os.makedirs(fdir)
+            out = file(self.lastboot, 'wb+')
+            out.write(val)
+            out.close()
+        except IOError, ex:
+            print 'warning: Error writing', self.lastboot, ex
+            pass
+
+    def check_lastboot(self):
+        """Check if there has been a system reboot since we saved lastboot.
+        """
+        last_val = self.read_lastboot()
+        this_val = last_reboot()
+        if this_val == last_val:
+            self.rebooted = 0
+        else:
+            self.rebooted = 1
+            self.write_lastboot(this_val)
+        self.last_reboot = this_val
+
+    def get_last_reboot(self):
+        return self.last_reboot
+
+    def get_rebooted(self):
+        return self.rebooted
+
+    def configure(self):
+        self.set_config()
+        self.dbroot = self.get_config_value("dbroot", self.dbroot_default)
+        self.lastboot = self.get_config_value("lastboot", self.lastboot_default)
+
+    def get_dbroot(self):
+        """Get the path to the database root.
+        """
+        return self.dbroot
+
+    def set_config(self):
+        """If the config file exists, read it. If not, ignore it.
+
+        The config file is a sequence of sxp forms.
+        """
+        self.config_path = os.getenv(self.config_var, self.config_default)
+        if os.path.exists(self.config_path):
+            fin = file(self.config_path, 'rb')
+            try:
+                config = sxp.parse(fin)
+                config.insert(0, 'config')
+                self.config = config
+            finally:
+                fin.close()
+        else:
+            self.config = ['config']
+
+    def get_config(self, name=None):
+        """Get the configuration element with the given name, or
+        the whole configuration if no name is given.
+
+        name   element name (optional)
+        returns config or none
+        """
+        if name is None:
+            val = self.config
+        else:
+            val = sxp.child(self.config, name)
+        return val
+
+    def get_config_value(self, name, val=None):
+        """Get the value of an atomic configuration element.
+
+        name   element name
+        val    default value (optional, defaults to None)
+        returns value
+        """
+        return sxp.child_value(self.config, name, val=val)
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendRoot()
+    return inst
diff --git a/tools/xen/lib/xend/XendVnet.py b/tools/xen/lib/xend/XendVnet.py
new file mode 100644 (file)
index 0000000..213408e
--- /dev/null
@@ -0,0 +1,69 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Handler for vnet operations.
+"""
+
+import sxp
+import XendDB
+
+class XendVnet:
+    """Index of all vnets. Singleton.
+    """
+
+    dbpath = "vnet"
+
+    def __init__(self):
+        # Table of vnet info indexed by vnet id.
+        self.vnet = {}
+        self.db = XendDB.XendDB(self.dbpath)
+        self.vnet = self.db.fetchall("")
+
+    def vnet_ls(self):
+        """List all vnets.
+        """
+        return self.vnet.keys()
+
+    def vnets(self):
+        return self.vnet.values()
+
+    def vnet_get(self, id):
+        """Get a vnet.
+
+        id     vnet id
+        """
+        return self.vnet.get(id)
+
+    def vnet_create(self, info):
+        """Create a vnet.
+
+        info   config
+        """
+        self.vnet_configure(info)
+
+    def vnet_configure(self, info):
+        """Configure a vnet.
+        id     vnet id
+        info   config
+        """
+        # Need to configure for real.
+        # Only sync if succeeded - otherwise need to back out.
+        self.vnet[info.id] = info
+        self.db.save(info.id, info)
+
+    def vnet_delete(self, id):
+        """Delete a vnet.
+
+        id     vnet id
+        """
+        # Need to delete for real. What if fails?
+        if id in self.vnet:
+            del self.vnet[id]
+            self.db.delete(id)
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendVnet()
+    return inst
diff --git a/tools/xen/lib/xend/__init__.py b/tools/xen/lib/xend/__init__.py
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/tools/xen/lib/xend/encode.py b/tools/xen/lib/xend/encode.py
new file mode 100644 (file)
index 0000000..38c9351
--- /dev/null
@@ -0,0 +1,165 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Encoding for arguments to HTTP calls.
+   Uses the url-encoding with MIME type 'application/x-www-form-urlencoded'
+   if the data does not include files. Otherwise it uses the encoding with
+   MIME type 'multipart/form-data'. See the HTML4 spec for details.
+
+   """
+import sys
+import types
+from StringIO import StringIO
+
+import urllib
+import httplib
+import random
+import md5
+
+# Extract from HTML4 spec.
+## The following example illustrates "multipart/form-data"
+## encoding. Suppose we have the following form:
+
+##  <FORM action="http://server.com/cgi/handle"
+##        enctype="multipart/form-data"
+##        method="post">
+##    <P>
+##    What is your name? <INPUT type="text" name="submit-name"><BR>
+##    What files are you sending? <INPUT type="file" name="files"><BR>
+##    <INPUT type="submit" value="Send"> <INPUT type="reset">
+##  </FORM>
+
+## If the user enters "Larry" in the text input, and selects the text
+## file "file1.txt", the user agent might send back the following data:
+
+##    Content-Type: multipart/form-data; boundary=AaB03x
+
+##    --AaB03x
+##    Content-Disposition: form-data; name="submit-name"
+
+##    Larry
+##    --AaB03x
+##    Content-Disposition: form-data; name="files"; filename="file1.txt"
+##    Content-Type: text/plain
+
+##    ... contents of file1.txt ...
+##    --AaB03x--
+
+## If the user selected a second (image) file "file2.gif", the user agent
+## might construct the parts as follows:
+
+##    Content-Type: multipart/form-data; boundary=AaB03x
+
+##    --AaB03x
+##    Content-Disposition: form-data; name="submit-name"
+
+##    Larry
+##    --AaB03x
+##    Content-Disposition: form-data; name="files"
+##    Content-Type: multipart/mixed; boundary=BbC04y
+
+##    --BbC04y
+##    Content-Disposition: file; filename="file1.txt"
+##    Content-Type: text/plain
+
+##    ... contents of file1.txt ...
+##    --BbC04y
+##    Content-Disposition: file; filename="file2.gif"
+##    Content-Type: image/gif
+##    Content-Transfer-Encoding: binary
+
+##    ...contents of file2.gif...
+##    --BbC04y--
+##    --AaB03x--
+
+__all__ = ['encode_data', 'encode_multipart', 'encode_form', 'mime_boundary' ]
+
+def data_values(d):
+    if isinstance(d, types.DictType):
+        return d.items()
+    else:
+        return d
+
+def encode_data(d):
+    """Encode some data for HTTP transport.
+    The encoding used is stored in 'Content-Type' in the headers.
+
+    d  data - sequence of tuples or dictionary
+    returns a 2-tuple of the headers and the encoded data
+    """
+    val = ({}, None)
+    if d is None: return val
+    multipart = 0
+    for (k, v) in data_values(d):
+        if encode_isfile(v):
+            multipart = 1
+            break
+    if multipart:
+        val = encode_multipart(d)
+    else:
+        val = encode_form(d)
+    return val
+
+def encode_isfile(v):
+    if isinstance(v, types.FileType):
+        return 1
+    if hasattr(v, 'readlines'):
+        return 1
+    return 0
+
+def encode_multipart(d):
+    boundary = mime_boundary()
+    hdr = { 'Content-Type': 'multipart/form-data; boundary=' + boundary }
+    out = StringIO()
+    for (k,v) in data_values(d):
+        out.write('--')
+        out.write(boundary)
+        out.write('\r\n')
+        if encode_isfile(v):
+            out.write('Content-Disposition: form-data; name="')
+            out.write(k)
+            if hasattr(v, 'name'):
+                out.write('"; filename="')
+                out.write(v.name)
+            out.write('"\r\n')
+            out.write('Content-Type: application/octet-stream\r\n')
+            out.write('\r\n')
+            for l in v.readlines():
+               out.write(l)  
+        else:
+            out.write('Content-Disposition: form-data; name="')
+            out.write(k)
+            out.write('"\r\n')
+            out.write('\r\n')
+            out.write(str(v))
+            out.write('\r\n')
+    out.write('--')
+    out.write(boundary)
+    out.write('--')
+    out.write('\r\n')
+    return (hdr, out.getvalue())
+
+def mime_boundary():
+    random.seed()
+    m = md5.new()
+    for i in range(0, 10):
+        c = chr(random.randint(1, 255))
+        m.update(c)
+    b = m.hexdigest()
+    return b[0:16]
+
+def encode_form(d):
+    hdr = { 'Content-Type': 'application/x-www-form-urlencoded' }
+    val = urllib.urlencode(d)
+    return (hdr, val)
+
+def main():
+    #d = {'a': 1, 'b': 'x y', 'c': file('conf.sxp') }
+    #d = {'a': 1, 'b': 'x y' }
+    d = [ ('a', 1), ('b', 'x y'), ('c', file('conf.sxp')) ]
+    #d = [ ('a', 1), ('b', 'x y')]
+    v = encode_data(d)
+    print v[0]
+    sys.stdout.write(v[1])
+    print
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/xen/lib/xend/server/SrvBase.py b/tools/xen/lib/xend/server/SrvBase.py
new file mode 100644 (file)
index 0000000..bcff1bc
--- /dev/null
@@ -0,0 +1,137 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+import cgi
+
+import os
+import sys
+import types
+import StringIO
+
+from twisted.internet import defer
+from twisted.internet import reactor
+from twisted.web import error
+from twisted.web import resource
+from twisted.web import server
+
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+
+def uri_pathlist(p):
+    """Split a path into a list.
+    p          path
+    return list of path elements
+    """
+    l = []
+    for x in p.split('/'):
+        if x == '': continue
+        l.append(x)
+    return l
+
+class SrvBase(resource.Resource):
+    """Base class for services.
+    """
+
+    def parse_form(self, req, method):
+        """Parse the data for a request, GET using the URL, POST using encoded data.
+        Posts should use enctype='multipart/form-data' in the <form> tag,
+        rather than 'application/x-www-form-urlencoded'. Only 'multipart/form-data'
+        handles file upload.
+
+        req            request
+        returns a cgi.FieldStorage instance
+        """
+        env = {}
+        env['REQUEST_METHOD'] = method
+        if self.query:
+            env['QUERY_STRING'] = self.query
+        val = cgi.FieldStorage(fp=req.rfile, headers=req.headers, environ=env)
+        return val
+    
+    def use_sxp(self, req):
+        """Determine whether to send an SXP response to a request.
+        Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept.
+
+        req            request
+        returns 1 for SXP, 0 otherwise
+        """
+        ok = 0
+        user_agent = req.getHeader('User-Agent')
+        accept = req.getHeader('Accept')
+        if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0):
+            ok = 1
+        return ok
+
+    def get_op_method(self, op):
+        """Get the method for an operation.
+        For operation 'foo' looks for 'op_foo'.
+
+        op     operation name
+        returns method or None
+        """
+        op_method_name = 'op_' + op
+        return getattr(self, op_method_name, None)
+        
+    def perform(self, req):
+        """General operation handler for posted operations.
+        For operation 'foo' looks for a method op_foo and calls
+        it with op_foo(op, req). Replies with code 500 if op_foo
+        is not found.
+
+        The method must return a list when req.use_sxp is true
+        and an HTML string otherwise (or list).
+        Methods may also return a Deferred (for incomplete processing).
+
+        req    request
+        """
+        op = req.args.get('op')
+        if op is None or len(op) != 1:
+            req.setResponseCode(404, "Invalid")
+            return ''
+        op = op[0]
+        op_method = self.get_op_method(op)
+        if op_method is None:
+            req.setResponseCode(501, "Not implemented")
+            req.setHeader("Content-Type", "text/plain")
+            req.write("Not implemented: " + op)
+            return ''
+        else:
+            val = op_method(op, req)
+            if isinstance(val, defer.Deferred):
+                val.addCallback(self._cb_perform, req, 1)
+                return server.NOT_DONE_YET
+            else:
+                self._cb_perform(val, req, 0)
+                return ''
+
+    def _cb_perform(self, val, req, dfr):
+        """Callback to complete the request.
+        May be called from a Deferred.
+        """
+        if isinstance(val, error.ErrorPage):
+            req.write(val.render(req))
+        elif self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            sxp.show(val, req)
+        else:
+            req.write('<html><head></head><body>')
+            self.print_path(req)
+            if isinstance(val, types.ListType):
+                req.write('<code><pre>')
+                PrettyPrint.prettyprint(val, out=req)
+                req.write('</pre></code>')
+            else:
+                req.write(str(val))
+            req.write('</body></html>')
+        if dfr:
+            req.finish()
+
+    def print_path(self, req):
+        """Print the path with hyperlinks.
+        """
+        pathlist = [x for x in req.prepath if x != '' ]
+        s = "/"
+        req.write('<h1><a href="/">/</a>')
+        for x in pathlist:
+            s += x + "/"
+            req.write(' <a href="%s">%s</a>/' % (s, x))
+        req.write("</h1>")
diff --git a/tools/xen/lib/xend/server/SrvConsole.py b/tools/xen/lib/xend/server/SrvConsole.py
new file mode 100644 (file)
index 0000000..59d0e5f
--- /dev/null
@@ -0,0 +1,42 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from xen.xend import sxp
+from xen.xend import XendConsole
+from SrvDir import SrvDir
+
+class SrvConsole(SrvDir):
+    """An individual console.
+    """
+
+    def __init__(self, info):
+        SrvDir.__init__(self)
+        self.info = info
+        self.xc = XendConsole.instance()
+
+    def op_disconnect(self, op, req):
+        val = self.xc.console_disconnect(self.info.id)
+        return val
+
+    def render_POST(self, req):
+        return self.perform(req)
+        
+    def render_GET(self, req):
+        if self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            sxp.show(self.info.sxpr(), out=req)
+        else:
+            req.write('<html><head></head><body>')
+            self.print_path(req)
+            #self.ls()
+            req.write('<p>%s</p>' % self.info)
+            req.write('<p><a href="%s">Connect to domain %d</a></p>'
+                      % (self.info.uri(), self.info.dom2))
+            self.form(req)
+            req.write('</body></html>')
+        return ''
+
+    def form(self, req):
+        req.write('<form method="post" action="%s">' % req.prePathURL())
+        if self.info.connection():
+            req.write('<input type="submit" name="op" value="disconnect">')
+        req.write('</form>')
diff --git a/tools/xen/lib/xend/server/SrvConsoleDir.py b/tools/xen/lib/xend/server/SrvConsoleDir.py
new file mode 100644 (file)
index 0000000..814b448
--- /dev/null
@@ -0,0 +1,59 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from SrvDir import SrvDir
+from SrvConsole import SrvConsole
+from xen.xend import XendConsole
+from xen.xend import sxp
+
+class SrvConsoleDir(SrvDir):
+    """Console directory.
+    """
+
+    def __init__(self):
+        SrvDir.__init__(self)
+        self.xconsole = XendConsole.instance()
+
+    def console(self, x):
+        val = None
+        try:
+            info = self.xconsole.console_get(x)
+            val = SrvConsole(info)
+        except KeyError, ex:
+            print 'SrvConsoleDir>', ex
+            pass
+        return val
+
+    def get(self, x):
+        v = SrvDir.get(self, x)
+        if v is not None:
+            return v
+        v = self.console(x)
+        return v
+
+    def render_GET(self, req):
+        if self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            self.ls_console(req, 1)
+        else:
+            req.write("<html><head></head><body>")
+            self.print_path(req)
+            self.ls(req)
+            self.ls_console(req)
+            #self.form(req.wfile)
+            req.write("</body></html>")
+        return ''
+
+    def ls_console(self, req, use_sxp=0):
+        url = req.prePathURL()
+        if not url.endswith('/'):
+            url += '/'
+        if use_sxp:
+            consoles = self.xconsole.console_ls()
+            sxp.show(consoles, out=req)
+        else:
+            consoles = self.xconsole.consoles()
+            consoles.sort(lambda x, y: cmp(x.id, y.id))
+            req.write('<ul>')
+            for c in consoles:
+                req.write('<li><a href="%s%s"> %s</a></li>' % (url, c.id, c))
+            req.write('</ul>')
diff --git a/tools/xen/lib/xend/server/SrvDaemon.py b/tools/xen/lib/xend/server/SrvDaemon.py
new file mode 100644 (file)
index 0000000..385588b
--- /dev/null
@@ -0,0 +1,704 @@
+###########################################################
+## Xen controller daemon
+## Copyright (c) 2004, K A Fraser (University of Cambridge)
+## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
+###########################################################
+
+import os
+import os.path
+import signal
+import sys
+import socket
+import pwd
+import re
+import StringIO
+
+from twisted.internet import pollreactor
+pollreactor.install()
+
+from twisted.internet import reactor
+from twisted.internet import protocol
+from twisted.internet import abstract
+from twisted.internet import defer
+
+from xen.ext import xu
+
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+from xen.xend import EventServer
+eserver = EventServer.instance()
+
+from xen.xend.server import SrvServer
+
+import channel
+import blkif
+import netif
+import console
+import domain
+from params import *
+
+DEBUG = 1
+
+class MgmtProtocol(protocol.DatagramProtocol):
+    """Handler for the management socket (unix-domain).
+    """
+
+    def __init__(self, daemon):
+        #protocol.DatagramProtocol.__init__(self)
+        self.daemon = daemon
+    
+    def write(self, data, addr):
+        return self.transport.write(data, addr)
+
+    def datagramReceived(self, data, addr):
+        if DEBUG: print 'datagramReceived> addr=', addr, 'data=', data
+        io = StringIO.StringIO(data)
+        try:
+            vals = sxp.parse(io)
+            res = self.dispatch(vals[0])
+            self.send_result(addr, res)
+        except SystemExit:
+            raise
+        except:
+            if DEBUG:
+                raise
+            else:
+                self.send_error(addr)
+
+    def send_reply(self, addr, sxpr):
+        io = StringIO.StringIO()
+        sxp.show(sxpr, out=io)
+        io.seek(0)
+        self.write(io.getvalue(), addr)
+
+    def send_result(self, addr, res):
+        
+        def fn(res, self=self, addr=addr):
+            self.send_reply(addr, ['ok', res])
+            
+        if isinstance(res, defer.Deferred):
+            res.addCallback(fn)
+        else:
+            fn(res)
+
+    def send_error(self, addr):
+        (extype, exval) = sys.exc_info()[:2]
+        self.send_reply(addr, ['err',
+                               ['type',  str(extype) ],
+                               ['value', str(exval)  ] ] )
+
+    def opname(self, name):
+        """Get the name of the method for an operation.
+        """
+        return 'op_' + name.replace('.', '_')
+
+    def operror(self, name, v):
+        """Default operation handler - signals an error.
+        """
+        raise NotImplementedError('Invalid operation: ' +name)
+
+    def dispatch(self, req):
+        """Dispatch a request to its handler.
+        """
+        op_name = sxp.name(req)
+        op_method_name = self.opname(op_name)
+        op_method = getattr(self, op_method_name, self.operror)
+        return op_method(op_name, req)
+
+    def op_console_create(self, name, req):
+        """Create a new control interface - console for a domain.
+        """
+        print name, req
+        dom = sxp.child_value(req, 'domain')
+        if not dom: raise ValueError('Missing domain')
+        dom = int(dom)
+        console_port = sxp.child_value(req, 'console_port')
+        if console_port:
+            console_port = int(console_port)
+        resp = self.daemon.console_create(dom, console_port)
+        print name, resp
+        return resp
+
+    def op_consoles(self, name, req):
+        """Get a list of the consoles.
+        """
+        return self.daemon.consoles()
+
+    def op_console_disconnect(self, name, req):
+        id = sxp.child_value(req, 'id')
+        if not id:
+            raise ValueError('Missing console id')
+        id = int(id)
+        console = self.daemon.get_console(id)
+        if not console:
+            raise ValueError('Invalid console id')
+        if console.conn:
+            console.conn.loseConnection()
+        return ['ok']
+
+    def op_blkifs(self, name, req):
+        pass
+    
+    def op_blkif_devs(self, name, req):
+        pass
+
+    def op_blkif_create(self, name, req):
+        pass
+    
+    def op_blkif_dev_create(self, name, req):
+        pass
+
+    def op_netifs(self, name, req):
+        pass
+
+    def op_netif_devs(self, name, req):
+        pass
+
+    def op_netif_create(self, name, req):
+        pass
+
+    def op_netif_dev_create(self, name, req):
+        pass
+
+class NotifierProtocol(protocol.Protocol):
+    """Asynchronous handler for i/o on the notifier (event channel).
+    """
+
+    def __init__(self, channelFactory):
+        self.channelFactory = channelFactory
+
+    def notificationReceived(self, idx, type):
+        #print 'NotifierProtocol>notificationReceived>', idx, type
+        channel = self.channelFactory.getChannel(idx)
+        if not channel:
+            return
+        #print 'NotifierProtocol>notificationReceived> channel', channel
+        channel.notificationReceived(type)
+
+    def connectionLost(self, reason=None):
+        pass
+
+    def doStart(self):
+        pass
+
+    def doStop(self):
+        pass
+
+    def startProtocol(self):
+        pass
+
+    def stopProtocol(self):
+        pass
+
+class NotifierPort(abstract.FileDescriptor):
+    """Transport class for the event channel.
+    """
+
+    def __init__(self, daemon, notifier, proto, reactor=None):
+        assert isinstance(proto, NotifierProtocol)
+        abstract.FileDescriptor.__init__(self, reactor)
+        self.daemon = daemon
+        self.notifier = notifier
+        self.protocol = proto
+
+    def startListening(self):
+        self._bindNotifier()
+        self._connectToProtocol()
+
+    def stopListening(self):
+        if self.connected:
+            result = self.d = defer.Deferred()
+        else:
+            result = None
+        self.loseConnection()
+        return result
+
+    def fileno(self):
+        return self.notifier.fileno()
+
+    def _bindNotifier(self):
+        self.connected = 1
+
+    def _connectToProtocol(self):
+        self.protocol.makeConnection(self)
+        self.startReading()
+
+    def loseConnection(self):
+        if self.connected:
+            self.stopReading()
+            self.disconnecting = 1
+            reactor.callLater(0, self.connectionLost)
+
+    def connectionLost(self, reason=None):
+        abstract.FileDescriptor.connectionLost(self, reason)
+        if hasattr(self, 'protocol'):
+            self.protocol.doStop()
+        self.connected = 0
+        #self.notifier.close() # Not implemented.
+        os.close(self.fileno())
+        del self.notifier
+        if hasattr(self, 'd'):
+            self.d.callback(None)
+            del self.d
+        
+    def doRead(self):
+        #print 'NotifierPort>doRead>', self
+        count = 0
+        while 1:            
+            #print 'NotifierPort>doRead>', count
+            notification = self.notifier.read()
+            if not notification:
+                break
+            (idx, type) = notification
+            self.protocol.notificationReceived(idx, type)
+            self.notifier.unmask(idx)
+            count += 1
+        #print 'NotifierPort>doRead<'
+
+class EventProtocol(protocol.Protocol):
+    """Asynchronous handler for a connected event socket.
+    """
+
+    def __init__(self, daemon):
+        #protocol.Protocol.__init__(self)
+        self.daemon = daemon
+        # Event queue.
+        self.queue = []
+        # Subscribed events.
+        self.events = []
+        self.parser = sxp.Parser()
+        self.pretty = 0
+
+        # For debugging subscribe to everything and make output pretty.
+        self.subscribe(['*'])
+        self.pretty = 1
+
+    def dataReceived(self, data):
+        try:
+            self.parser.input(data)
+            if self.parser.ready():
+                val = self.parser.get_val()
+                res = self.dispatch(val)
+                self.send_result(res)
+            if self.parser.at_eof():
+                self.loseConnection()
+        except SystemExit:
+            raise
+        except:
+            if DEBUG:
+                raise
+            else:
+                self.send_error()
+
+    def loseConnection(self):
+        if self.transport:
+            self.transport.loseConnection()
+        if self.connected:
+            reactor.callLater(0, self.connectionLost)
+
+    def connectionLost(self, reason=None):
+        self.unsubscribe()
+
+    def send_reply(self, sxpr):
+        io = StringIO.StringIO()
+        if self.pretty:
+            PrettyPrint.prettyprint(sxpr, out=io)
+        else:
+            sxp.show(sxpr, out=io)
+        print >> io
+        io.seek(0)
+        return self.transport.write(io.getvalue())
+
+    def send_result(self, res):
+        return self.send_reply(['ok', res])
+
+    def send_error(self):
+        (extype, exval) = sys.exc_info()[:2]
+        return self.send_reply(['err',
+                                ['type', str(extype)],
+                                ['value', str(exval)]])
+
+    def send_event(self, val):
+        return self.send_reply(['event', val[0], val[1]])
+
+    def unsubscribe(self):
+        for event in self.events:
+            eserver.unsubscribe(event, self.queue_event)
+
+    def subscribe(self, events):
+        self.unsubscribe()
+        for event in events:
+            eserver.subscribe(event, self.queue_event)
+        self.events = events
+
+    def queue_event(self, name, v):
+        # Despite the name we dont' queue the event here.
+        # We send it because the transport will queue it.
+        self.send_event([name, v])
+        
+    def opname(self, name):
+         return 'op_' + name.replace('.', '_')
+
+    def operror(self, name, req):
+        raise NotImplementedError('Invalid operation: ' +name)
+
+    def dispatch(self, req):
+        op_name = sxp.name(req)
+        op_method_name = self.opname(op_name)
+        op_method = getattr(self, op_method_name, self.operror)
+        return op_method(op_name, req)
+
+    def op_help(self, name, req):
+        def nameop(x):
+            if x.startswith('op_'):
+                return x[3:].replace('_', '.')
+            else:
+                return x
+        
+        l = [ nameop(k) for k in dir(self) if k.startswith('op_') ]
+        return l
+
+    def op_quit(self, name, req):
+        self.loseConnection()
+
+    def op_exit(self, name, req):
+        sys.exit(0)
+
+    def op_pretty(self, name, req):
+        self.pretty = 1
+        return ['ok']
+
+    def op_console_disconnect(self, name, req):
+        id = sxp.child_value(req, 'id')
+        if not id:
+            raise ValueError('Missing console id')
+        self.daemon.console_disconnect(id)
+        return ['ok']
+
+    def op_info(self, name, req):
+        val = ['info']
+        val += self.daemon.consoles()
+        val += self.daemon.blkifs()
+        val += self.daemon.netifs()
+        return val
+
+    def op_sys_subscribe(self, name, v):
+        # (sys.subscribe event*)
+        # Subscribe to the events:
+        self.subscribe(v[1:])
+        return ['ok']
+
+    def op_sys_inject(self, name, v):
+        # (sys.inject event)
+        event = v[1]
+        eserver.inject(sxp.name(event), event)
+        return ['ok']
+
+
+class EventFactory(protocol.Factory):
+    """Asynchronous handler for the event server socket.
+    """
+    protocol = EventProtocol
+    service = None
+
+    def __init__(self, daemon):
+        #protocol.Factory.__init__(self)
+        self.daemon = daemon
+
+    def buildProtocol(self, addr):
+        proto = self.protocol(self.daemon)
+        proto.factory = self
+        return proto
+
+class VirqClient:
+    def __init__(self, daemon):
+        self.daemon = daemon
+
+    def virqReceived(self, virq):
+        print 'VirqClient.virqReceived>', virq
+        eserver.inject('xend.virq', virq)
+
+    def lostChannel(self, channel):
+        print 'VirqClient.lostChannel>', channel
+        
+class Daemon:
+    """The xend daemon.
+    """
+    def __init__(self):
+        self.shutdown = 0
+
+    def daemon_pids(self):
+        pids = []
+        pidex = '(?P<pid>\d+)'
+        pythonex = '(?P<python>\S*python\S*)'
+        cmdex = '(?P<cmd>.*)'
+        procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
+        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
+        procs = os.popen('ps -e -o pid,args 2>/dev/null')
+        for proc in procs:
+            pm = procre.match(proc)
+            if not pm: continue
+            xm = xendre.match(pm.group('cmd'))
+            if not xm: continue
+            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
+            pids.append(int(pm.group('pid')))
+        return pids
+
+    def new_cleanup(self, kill=0):
+        err = 0
+        pids = self.daemon_pids()
+        if kill:
+            for pid in pids:
+                print "Killing daemon pid=%d" % pid
+                os.kill(pid, signal.SIGHUP)
+        elif pids:
+            err = 1
+            print "Daemon already running: ", pids
+        return err
+            
+    def cleanup(self, kill=False):
+        # No cleanup to do if PID_FILE is empty.
+        if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
+            return 0
+        # Read the pid of the previous invocation and search active process list.
+        pid = open(PID_FILE, 'r').read()
+        lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
+        for line in lines:
+            if re.search('^ *' + pid + '.+xend', line):
+                if not kill:
+                    print "Daemon is already running (pid %d)" % int(pid)
+                    return 1
+                # Old daemon is still active: terminate it.
+                os.kill(int(pid), 1)
+        # Delete the stale PID_FILE.
+        os.remove(PID_FILE)
+        return 0
+
+    def install_child_reaper(self):
+        #signal.signal(signal.SIGCHLD, self.onSIGCHLD)
+        # Ensure that zombie children are automatically reaped.
+        xu.autoreap()
+
+    def onSIGCHLD(self, signum, frame):
+        code = 1
+        while code > 0:
+            code = os.waitpid(-1, os.WNOHANG)
+
+    def start(self):
+        if self.cleanup(kill=False):
+            return 1
+
+        # Detach from TTY.
+        if not DEBUG:
+            os.setsid()
+
+        if self.set_user():
+            return 1
+
+        self.install_child_reaper()
+
+        # Fork -- parent writes PID_FILE and exits.
+        pid = os.fork()
+        if pid:
+            # Parent
+            pidfile = open(PID_FILE, 'w')
+            pidfile.write(str(pid))
+            pidfile.close()
+            return 0
+        # Child
+        logfile = self.open_logfile()
+        self.redirect_output(logfile)
+        self.run()
+        return 0
+
+    def open_logfile(self):
+        if not os.path.exists(CONTROL_DIR):
+            os.makedirs(CONTROL_DIR)
+
+        # Open log file. Truncate it if non-empty, and request line buffering.
+        if os.path.isfile(LOG_FILE):
+            os.rename(LOG_FILE, LOG_FILE+'.old')
+        logfile = open(LOG_FILE, 'w+', 1)
+        return logfile
+
+    def set_user(self):
+        # Set the UID.
+        try:
+            os.setuid(pwd.getpwnam(USER)[2])
+            return 0
+        except KeyError, error:
+            print "Error: no such user '%s'" % USER
+            return 1
+
+    def redirect_output(self, logfile):
+        if DEBUG: return
+        # Close down standard file handles
+        try:
+            os.close(0) # stdin
+            os.close(1) # stdout
+            os.close(2) # stderr
+        except:
+            pass
+        # Redirect output to log file.
+        sys.stdout = sys.stderr = logfile
+
+    def stop(self):
+        return self.cleanup(kill=True)
+
+    def run(self):
+        self.createFactories()
+        self.listenMgmt()
+        self.listenEvent()
+        self.listenNotifier()
+        self.listenVirq()
+        SrvServer.create(bridge=1)
+        reactor.run()
+
+    def createFactories(self):
+        self.channelF = channel.channelFactory()
+        self.domainCF = domain.DomainControllerFactory()
+        self.blkifCF = blkif.BlkifControllerFactory()
+        self.netifCF = netif.NetifControllerFactory()
+        self.consoleCF = console.ConsoleControllerFactory()
+
+    def listenMgmt(self):
+        protocol = MgmtProtocol(self)
+        s = os.path.join(CONTROL_DIR, MGMT_SOCK)
+        if os.path.exists(s):
+            os.unlink(s)
+        return reactor.listenUNIXDatagram(s, protocol)
+
+    def listenEvent(self):
+        protocol = EventFactory(self)
+        return reactor.listenTCP(EVENT_PORT, protocol)
+
+    def listenNotifier(self):
+        protocol = NotifierProtocol(self.channelF)
+        p = NotifierPort(self, self.channelF.notifier, protocol, reactor)
+        p.startListening()
+        return p
+
+    def listenVirq(self):
+        virqChan = self.channelF.virqChannel(channel.VIRQ_DOM_EXC)
+        virqChan.registerClient(VirqClient(self))
+
+    def exit(self):
+        reactor.diconnectAll()
+        sys.exit(0)
+
+    def blkif_set_control_domain(self, dom, recreate=0):
+        """Set the block device backend control domain.
+        """
+        return self.blkifCF.setControlDomain(dom, recreate=recreate)
+    
+    def blkif_get_control_domain(self, dom):
+        """Get the block device backend control domain.
+        """
+        return self.blkifCF.getControlDomain()
+    
+    def blkif_create(self, dom, recreate=0):
+        """Create a block device interface controller.
+        
+        Returns Deferred
+        """
+        d = self.blkifCF.createInstance(dom, recreate=recreate)
+        return d
+
+    def blkifs(self):
+        return [ x.sxpr() for x in self.blkifCF.getInstances() ]
+
+    def blkif_get(self, dom):
+        return self.blkifCF.getInstanceByDom(dom)
+
+    def blkif_dev(self, dom, vdev):
+        return self.blkifCF.getDomainDevice(dom, vdev)
+
+    def blkif_dev_create(self, dom, vdev, mode, segment, recreate=0):
+        """Create a block device.
+        
+        Returns Deferred
+        """
+        ctrl = self.blkifCF.getInstanceByDom(dom)
+        if not ctrl:
+            raise ValueError('No blkif controller: %d' % dom)
+        print 'blkif_dev_create>', dom, vdev, mode, segment
+        d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate)
+        return d
+
+    def netif_set_control_domain(self, dom, recreate=0):
+        """Set the network interface backend control domain.
+        """
+        return self.netifCF.setControlDomain(dom, recreate=recreate)
+
+    def netif_get_control_domain(self, dom):
+        """Get the network interface backend control domain.
+        """
+        return self.netifCF.getControlDomain()
+    
+    def netif_create(self, dom, recreate=0):
+        """Create a network interface controller.
+        
+        """
+        return self.netifCF.createInstance(dom, recreate=recreate)
+
+    def netifs(self):
+        return [ x.sxpr() for x in self.netifCF.getInstances() ]
+
+    def netif_get(self, dom):
+        return self.netifCF.getInstanceByDom(dom)
+
+    def netif_dev_create(self, dom, vif, vmac, recreate=0):
+        """Create a network device.
+
+        todo
+        """
+        ctrl = self.netifCF.getInstanceByDom(dom)
+        if not ctrl:
+            raise ValueError('No netif controller: %d' % dom)
+        d = ctrl.attachDevice(vif, vmac, recreate=recreate)
+        return d
+
+    def netif_dev(self, dom, vif):
+        return self.netifCF.getDomainDevice(dom, vif)
+
+    def console_create(self, dom, console_port=None):
+        """Create a console for a domain.
+        """
+        console = self.consoleCF.getInstanceByDom(dom)
+        if console is None:
+            console = self.consoleCF.createInstance(dom, console_port)
+        return console.sxpr()
+
+    def consoles(self):
+        return [ c.sxpr() for c in self.consoleCF.getInstances() ]
+
+    def get_console(self, id):
+        return self.consoleCF.getInstance(id)
+
+    def get_domain_console(self, dom):
+        return self.consoleCF.getInstanceByDom(dom)
+
+    def console_disconnect(self, id):
+        """Disconnect any connected console client.
+        """
+        console = self.get_console(id)
+        if not console:
+            raise ValueError('Invalid console id')
+        console.disconnect()
+
+    def domain_shutdown(self, dom, reason):
+        """Shutdown a domain.
+        """
+        ctrl = self.domainCF.getInstanceByDom(dom)
+        if not ctrl:
+            raise ValueError('No domain controller: %d' % dom)
+        ctrl.shutdown(reason)
+        return 0
+        
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = Daemon()
+    return inst
diff --git a/tools/xen/lib/xend/server/SrvDeviceDir.py b/tools/xen/lib/xend/server/SrvDeviceDir.py
new file mode 100644 (file)
index 0000000..52f4285
--- /dev/null
@@ -0,0 +1,9 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from SrvDir import SrvDir
+
+class SrvDeviceDir(SrvDir):
+    """Device directory.
+    """
+
+    pass
diff --git a/tools/xen/lib/xend/server/SrvDir.py b/tools/xen/lib/xend/server/SrvDir.py
new file mode 100644 (file)
index 0000000..c49c0b3
--- /dev/null
@@ -0,0 +1,91 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from twisted.web import error
+from xen.xend import sxp
+from SrvBase import SrvBase
+
+class SrvConstructor:
+    """Delayed constructor for sub-servers.
+    Does not import the sub-server class or create the object until needed.
+    """
+    
+    def __init__(self, klass):
+        """Create a constructor. It is assumed that the class
+        should be imported as 'import klass from klass'.
+
+        klass  name of its class
+        """
+        self.klass = klass
+        self.obj = None
+
+    def getobj(self):
+        """Get the sub-server object, importing its class and instantiating it if
+        necessary.
+        """
+        if not self.obj:
+            exec 'from %s import %s' % (self.klass, self.klass)
+            klassobj = eval(self.klass)
+            self.obj = klassobj()
+        return self.obj
+
+class SrvDir(SrvBase):
+    """Base class for directory servlets.
+    """
+    isLeaf = False
+    
+    def __init__(self):
+        SrvBase.__init__(self)
+        self.table = {}
+        self.order = []
+
+    def getChild(self, x, req):
+        if x == '': return self
+        val = self.get(x)
+        if val is None:
+            return error.NoResource('Not found')
+        else:
+            return val
+
+    def get(self, x):
+        val = self.table.get(x)
+        if val is not None:
+            val = val.getobj()
+        return val
+
+    def add(self, x, xclass = None):
+        if xclass is None:
+            xclass = 'SrvDir'
+        self.table[x] = SrvConstructor(xclass)
+        self.order.append(x)
+
+    def render_GET(self, req):
+        if self.use_sxp(req):
+            req.setHeader("Content-type", sxp.mime_type)
+            self.ls(req, 1)
+        else:
+            req.write('<html><head></head><body>')
+            self.print_path(req)
+            self.ls(req)
+            self.form(req)
+            req.write('</body></html>')
+        return ''
+            
+    def ls(self, req, use_sxp=0):
+        url = req.prePathURL()
+        if not url.endswith('/'):
+            url += '/'
+        if use_sxp:
+           req.write('(ls ')
+           for k in self.order:
+               req.write(' ' + k)
+           req.write(')')
+        else:
+            req.write('<ul>')
+            for k in self.order:
+                v = self.get(k)
+                req.write('<li><a href="%s%s">%s</a></li>'
+                          % (url, k, k))
+            req.write('</ul>')
+
+    def form(self, req):
+        pass
diff --git a/tools/xen/lib/xend/server/SrvDomain.py b/tools/xen/lib/xend/server/SrvDomain.py
new file mode 100644 (file)
index 0000000..c3684f2
--- /dev/null
@@ -0,0 +1,202 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from xen.xend import sxp
+from xen.xend import XendDomain
+from xen.xend import XendConsole
+from xen.xend import PrettyPrint
+from xen.xend.Args import FormFn
+
+from SrvDir import SrvDir
+
+class SrvDomain(SrvDir):
+    """Service managing a single domain.
+    """
+
+    def __init__(self, dom):
+        SrvDir.__init__(self)
+        self.dom = dom
+        self.xd = XendDomain.instance()
+        self.xconsole = XendConsole.instance()
+
+    def op_unpause(self, op, req):
+        val = self.xd.domain_unpause(self.dom.id)
+        return val
+        
+    def op_pause(self, op, req):
+        val = self.xd.domain_pause(self.dom.id)
+        return val
+
+    def op_shutdown(self, op, req):
+        val = self.xd.domain_shutdown(self.dom.id)
+        req.setResponseCode(202)
+        req.setHeader("Location", "%s/.." % req.prePathURL())
+        return val
+
+    def op_destroy(self, op, req):
+        val = self.xd.domain_destroy(self.dom.id)
+        req.setHeader("Location", "%s/.." % req.prePathURL())
+        return val
+
+    def op_save(self, op, req):
+        fn = FormFn(self.xd.domain_save,
+                    [['dom', 'int'],
+                     ['file', 'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_restore(self, op, req):
+        fn = FormFn(self.xd.domain_restore,
+                    [['dom', 'int'],
+                     ['file', 'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+        
+    def op_migrate(self, op, req):
+        fn = FormFn(self.xd.domain_migrate,
+                    [['dom', 'int'],
+                     ['destination', 'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        val = 0 # Some migrate id.
+        req.setResponseCode(202)
+        #req.send_header("Location", "%s/.." % self.path) # Some migrate url.
+        return val
+
+    def op_pincpu(self, op, req):
+        fn = FormFn(self.xd.domain_migrate,
+                    [['dom', 'int'],
+                     ['cpu', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_cpu_bvt_set(self, op, req):
+        fn = FormFn(self.xd.domain_cpu_bvt_set,
+                    [['dom', 'int'],
+                     ['mcuadv', 'int'],
+                     ['warp', 'int'],
+                     ['warpl', 'int'],
+                     ['warpu', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_cpu_atropos_set(self, op, req):
+        fn = FormFn(self.xd.domain_cpu_atropos_set,
+                    [['dom', 'int'],
+                     ['period', 'int'],
+                     ['slice', 'int'],
+                     ['latency', 'int'],
+                     ['xtratime', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vifs(self, op, req):
+        return self.xd.domain_vif_ls(self.dom.id)
+
+    def op_vif(self, op, req):
+        fn = FormFn(self.xd.domain_vif_get,
+                    [['dom', 'int'],
+                     ['vif', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vif_stats(self, op, req):
+        #todo
+        fn = FormFn(self.xd.domain_vif_stats,
+                    [['dom', 'int'],
+                     ['vif', 'int']])
+        #val = fn(req.args, {'dom': self.dom.id})
+        val = 999
+        #return val
+        return val
+
+    def op_vif_ip_add(self, op, req):
+        fn = FormFn(self.xd.domain_vif_ip_add,
+                    [['dom', 'int'],
+                     ['vif', 'int'],
+                     ['ip', 'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vif_scheduler_set(self, op, req):
+        fn = FormFn(self.xd.domain_vif_scheduler_set,
+                    [['dom', 'int'],
+                     ['vif', 'int'],
+                     ['bytes', 'int'],
+                     ['usecs', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vif_scheduler_get(self, op, req):
+        fn = FormFn(self.xd.domain_vif_scheduler_set,
+                    [['dom', 'int'],
+                     ['vif', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vbds(self, op, req):
+        return self.xd.domain_vbd_ls(self.dom.id)
+
+    def op_vbd(self, op, req):
+        fn = FormFn(self.xd.domain_vbd_get,
+                    [['dom', 'int'],
+                     ['vbd', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vbd_add(self, op, req):
+        fn = FormFn(self.xd.domain_vbd_add,
+                    [['dom', 'int'],
+                     ['uname', 'str'],
+                     ['dev', 'str'],
+                     ['mode', 'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vbd_remove(self, op, req):
+        fn = FormFn(self.xd.domain_vbd_remove,
+                    [['dom', 'int'],
+                     ['dev', 'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def render_POST(self, req):
+        return self.perform(req)
+        
+    def render_GET(self, req):
+        op = req.args.get('op')
+        if op and op[0] in ['vifs', 'vif', 'vif_stats', 'vbds', 'vbd']:
+            return self.perform(req)
+        if self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            sxp.show(self.dom.sxpr(), out=req)
+        else:
+            req.write('<html><head></head><body>')
+            self.print_path(req)
+            #self.ls()
+            req.write('<p>%s</p>' % self.dom)
+            if self.dom.console:
+                cinfo = self.dom.console
+                cid = cinfo.id
+                #todo: Local xref: need to know server prefix.
+                req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
+                          % (cid, cid))
+                req.write('<p><a href="%s">Connect to console</a></p>'
+                          % cinfo.uri())
+            if self.dom.config:
+                req.write("<code><pre>")
+                PrettyPrint.prettyprint(self.dom.config, out=req)
+                req.write("</pre></code>")
+            req.write('<a href="%s?op=vif_stats&vif=0">vif 0 stats</a>'
+                      % req.prePathURL())
+            self.form(req)
+            req.write('</body></html>')
+        return ''
+
+    def form(self, req):
+        req.write('<form method="post" action="%s">' % req.prePathURL())
+        req.write('<input type="submit" name="op" value="unpause">')
+        req.write('<input type="submit" name="op" value="pause">')
+        req.write('<input type="submit" name="op" value="shutdown">')
+        req.write('<input type="submit" name="op" value="destroy">')
+        req.write('<br><input type="submit" name="op" value="migrate">')
+        req.write('To: <input type="text" name="destination">')
+        req.write('</form>')
diff --git a/tools/xen/lib/xend/server/SrvDomainDir.py b/tools/xen/lib/xend/server/SrvDomainDir.py
new file mode 100644 (file)
index 0000000..cb5d8e3
--- /dev/null
@@ -0,0 +1,131 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from StringIO import StringIO
+
+from twisted.protocols import http
+from twisted.web import error
+
+from xen.xend import sxp
+from xen.xend import XendDomain
+
+from SrvDir import SrvDir
+from SrvDomain import SrvDomain
+
+class SrvDomainDir(SrvDir):
+    """Service that manages the domain directory.
+    """
+
+    def __init__(self):
+        SrvDir.__init__(self)
+        self.xd = XendDomain.instance()
+
+    def domain(self, x):
+        val = None
+        try:
+            dom = self.xd.domain_get(x)
+            val = SrvDomain(dom)
+        except KeyError, ex:
+            print 'SrvDomainDir>', ex
+            pass
+        return val
+
+    def get(self, x):
+        v = SrvDir.get(self, x)
+        if v is not None:
+            return v
+        v = self.domain(x)
+        return v
+
+    def op_create(self, op, req):
+        ok = 0
+        try:
+            configstring = req.args.get('config')[0]
+            print 'config:', configstring
+            pin = sxp.Parser()
+            pin.input(configstring)
+            pin.input_eof()
+            config = pin.get_val()
+            ok = 1
+        except Exception, ex:
+            print 'op_create>', ex
+        if not ok:
+            req.setResponseCode(http.BAD_REQUEST, "Invalid configuration")
+            return "Invalid configuration"
+            return error.ErrorPage(http.BAD_REQUEST,
+                                   "Invalid",
+                                   "Invalid configuration")
+        try:
+            deferred = self.xd.domain_create(config)
+            deferred.addCallback(self._cb_op_create, configstring, req)
+            return deferred
+        except Exception, ex:
+            raise
+            #return ['err', str(ex) ]
+            #req.setResponseCode(http.BAD_REQUEST, "Error creating domain")
+            #return str(ex)
+            #return error.ErrorPage(http.BAD_REQUEST,
+            #                       "Error creating domain",
+            #                       str(ex))
+                                   
+
+    def _cb_op_create(self, dominfo, configstring, req):
+        """Callback to handle deferred domain creation.
+        """
+        dom = dominfo.id
+        domurl = "%s/%s" % (req.prePathURL(), dom)
+        req.setResponseCode(201, "created")
+        req.setHeader("Location", domurl)
+        if self.use_sxp(req):
+            return dominfo.sxpr()
+        else:
+            out = StringIO()
+            print >> out, ('<p> Created <a href="%s">Domain %s</a></p>'
+                           % (domurl, dom))
+            print >> out, '<p><pre>'
+            print >> out, configstring
+            print >> out, '</pre></p>'
+            val = out.getvalue()
+            out.close()
+            return val
+
+    def render_POST(self, req):
+        return self.perform(req)
+
+    def render_GET(self, req):
+        if self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            self.ls_domain(req, 1)
+        else:
+            req.write("<html><head></head><body>")
+            self.print_path(req)
+            self.ls(req)
+            self.ls_domain(req)
+            self.form(req)
+            req.write("</body></html>")
+        return ''
+
+    def ls_domain(self, req, use_sxp=0):
+        url = req.prePathURL()
+        if not url.endswith('/'):
+            url += '/'
+        if use_sxp:
+            domains = self.xd.domain_ls()
+            sxp.show(domains, out=req)
+        else:
+            domains = self.xd.domains()
+            domains.sort(lambda x, y: cmp(x.id, y.id))
+            req.write('<ul>')
+            for d in domains:
+               req.write('<li><a href="%s%s"> Domain %s</a>'
+                         % (url, d.id, d.id))
+               req.write('name=%s' % d.name)
+               req.write('memory=%d'% d.memory)
+               req.write('</li>')
+            req.write('</ul>')
+
+    def form(self, req):
+        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
+                  % req.prePathURL())
+        req.write('<button type="submit" name="op" value="create">Create Domain</button>')
+        req.write('Config <input type="file" name="config"><br>')
+        req.write('</form>')
diff --git a/tools/xen/lib/xend/server/SrvEventDir.py b/tools/xen/lib/xend/server/SrvEventDir.py
new file mode 100644 (file)
index 0000000..02871a4
--- /dev/null
@@ -0,0 +1,41 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from xen.xend import sxp
+from xen.xend import EventServer
+from SrvDir import SrvDir
+
+class SrvEventDir(SrvDir):
+    """Event directory.
+    """
+
+    def __init__(self):
+        SrvDir.__init__(self)
+        self.eserver = EventServer.instance()
+
+    def op_inject(self, op, req):
+        eventstring = req.args.get('event')
+        pin = sxp.Parser()
+        pin.input(eventstring)
+        pin.input_eof()
+        sxpr = pin.get_val()
+        self.eserver.inject(sxp.name(sxpr), sxpr)
+        if req.use_sxp:
+            sxp.name(sxpr)
+        else:
+            return '<code>' + eventstring + '</code>'
+        
+    def render_POST(self, req):
+        return self.perform(req)
+
+    def form(self, req):
+        action = req.prePathURL()
+        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
+                  % action)
+        req.write('<button type="submit" name="op" value="inject">Inject</button>')
+        req.write('Event <input type="text" name="event" size="40"><br>')
+        req.write('</form>')
+        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
+                  % action)
+        req.write('<button type="submit" name="op" value="inject">Inject</button>')
+        req.write('Event file<input type="file" name="event"><br>')
+        req.write('</form>')
diff --git a/tools/xen/lib/xend/server/SrvNode.py b/tools/xen/lib/xend/server/SrvNode.py
new file mode 100644 (file)
index 0000000..69747d8
--- /dev/null
@@ -0,0 +1,54 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+import os
+from SrvDir import SrvDir
+from xen.xend import sxp
+from xen.xend import XendNode
+
+class SrvNode(SrvDir):
+    """Information about the node.
+    """
+
+    def __init__(self):
+        SrvDir.__init__(self)
+        self.xn = XendNode.instance()
+
+    def op_shutdown(self, op, req):
+        val = self.xn.shutdown()
+        return val
+
+    def op_reboot(self, op, req):
+        val = self.xn.reboot()
+        return val
+
+    def op_cpu_rrobin_slice_set(self, op, req):
+        fn = FormFn(self.xn.cpu_rrobin_slice_set,
+                    [['slice', 'int']])
+        val = fn(req.args, {})
+        return val
+
+    def op_cpu_bvt_slice_set(self, op, req):
+        fn = FormFn(self.xn.cpu_bvt_slice_set,
+                    [['slice', 'int']])
+        val = fn(req.args, {})
+        return val
+
+    def render_POST(self, req):
+        return self.perform(req)
+
+    def render_GET(self, req):
+        if self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            sxp.show(['node'] + self.info(), out=req)
+        else:
+            req.write('<html><head></head><body>')
+            self.print_path(req)
+            req.write('<ul>')
+            for d in self.info():
+                req.write('<li> %10s: %s' % (d[0], str(d[1])))
+            req.write('</ul>')
+            req.write('</body></html>')
+        return ''
+            
+    def info(self):
+        return self.xn.info()
diff --git a/tools/xen/lib/xend/server/SrvRoot.py b/tools/xen/lib/xend/server/SrvRoot.py
new file mode 100644 (file)
index 0000000..8d38937
--- /dev/null
@@ -0,0 +1,30 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from xen.xend import XendRoot
+xroot = XendRoot.instance()
+from SrvDir import SrvDir
+
+class SrvRoot(SrvDir):
+    """The root of the xend server.
+    """
+
+    """Server sub-components. Each entry is (name, class), where
+    'name' is the entry name and  'class' is the name of its class.
+    """
+    #todo Get this list from the XendRoot config.
+    subdirs = [
+        ('node',    'SrvNode'       ),
+        ('domain',  'SrvDomainDir'  ),
+        ('console', 'SrvConsoleDir' ),
+        ('event',   'SrvEventDir'   ),
+        ('device',  'SrvDeviceDir'  ),
+        ('vnet',    'SrvVnetDir'    ),
+        ]
+
+    def __init__(self):
+        SrvDir.__init__(self)
+        for (name, klass) in self.subdirs:
+            self.add(name, klass)
+        for (name, klass) in self.subdirs:
+            self.get(name)
+        xroot.start()
diff --git a/tools/xen/lib/xend/server/SrvServer.py b/tools/xen/lib/xend/server/SrvServer.py
new file mode 100644 (file)
index 0000000..6535ad3
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/python2
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Example xend HTTP and console server.
+
+   Can be accessed from a browser or from a program.
+   Do 'python SrvServer.py' to run the server.
+   Then point a web browser at http://localhost:8000/xend and follow the links.
+   Most are stubs, except /domain which has a list of domains and a 'create domain'
+   button.
+
+   You can also access the server from a program.
+   Do 'python XendClient.py' to run a few test operations.
+
+   The data served differs depending on the client (as defined by User-Agent
+   and Accept in the HTTP headers). If the client is a browser, data
+   is returned in HTML, with interactive forms. If the client is a program,
+   data is returned in SXP format, with no forms.
+
+   The server serves to the world by default. To restrict it to the local host
+   change 'interface' in main().
+
+   Mike Wray <mike.wray@hp.com>
+"""
+# todo Support security settings etc. in the config file.
+# todo Support command-line args.
+
+from twisted.web import server
+from twisted.web import resource
+from twisted.internet import reactor
+
+from xen.xend import XendRoot
+xroot = XendRoot.instance()
+
+from xen.xend import XendBridge
+
+from SrvRoot import SrvRoot
+
+def create(port=None, interface=None, bridge=0):
+    if port is None: port = 8000
+    if interface is None: interface = ''
+    if bridge or xroot.rebooted:
+        init_bridge()
+    root = resource.Resource()
+    xend = SrvRoot()
+    root.putChild('xend', xend)
+    site = server.Site(root)
+    reactor.listenTCP(port, site, interface=interface)
+
+def init_bridge():
+    XendBridge.bridge_create()
+    XendBridge.reconfigure()
+
+def main(port=None, interface=None):
+    create(port, interface)
+    reactor.run()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/xen/lib/xend/server/SrvVnetDir.py b/tools/xen/lib/xend/server/SrvVnetDir.py
new file mode 100644 (file)
index 0000000..a8a8141
--- /dev/null
@@ -0,0 +1,9 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from SrvDir import SrvDir
+
+class SrvVnetDir(SrvDir):
+    """Vnet directory.
+    """
+
+    pass
diff --git a/tools/xen/lib/xend/server/__init__.py b/tools/xen/lib/xend/server/__init__.py
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/tools/xen/lib/xend/server/blkif.py b/tools/xen/lib/xend/server/blkif.py
new file mode 100755 (executable)
index 0000000..4e2a49f
--- /dev/null
@@ -0,0 +1,341 @@
+from twisted.internet import defer
+
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+
+import channel
+import controller
+from messages import *
+
+class BlkifControllerFactory(controller.ControllerFactory):
+    """Factory for creating block device interface controllers.
+    Also handles the 'back-end' channel to the device driver domain.
+    """
+
+    def __init__(self):
+        controller.ControllerFactory.__init__(self)
+
+        self.majorTypes = [ CMSG_BLKIF_BE ]
+
+        self.subTypes = {
+            CMSG_BLKIF_BE_CREATE     : self.recv_be_create,
+            CMSG_BLKIF_BE_CONNECT    : self.recv_be_connect,
+            CMSG_BLKIF_BE_VBD_CREATE : self.recv_be_vbd_create,
+            CMSG_BLKIF_BE_VBD_GROW   : self.recv_be_vbd_grow,
+            CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
+            }
+        self.attached = 1
+        self.registerChannel()
+
+    def createInstance(self, dom, recreate=0):
+        d = self.addDeferred()
+        blkif = self.getInstanceByDom(dom)
+        if blkif:
+            self.callDeferred(blkif)
+        else:
+            blkif = BlkifController(self, dom)
+            self.addInstance(blkif)
+            if recreate:
+                self.callDeferred(blkif)
+            else:
+                blkif.send_be_create()
+        return d
+
+    def getDomainDevices(self, dom):
+        blkif = self.getInstanceByDom(dom)
+        return (blkif and blkif.getDevices()) or []
+
+    def getDomainDevice(self, dom, vdev):
+        blkif = self.getInstanceByDom(dom)
+        return (blkif and blkif.getDevice(vdev)) or None
+
+    def setControlDomain(self, dom, recreate=0):
+        if self.dom == dom: return
+        self.deregisterChannel()
+        if not recreate:
+            self.attached = 0
+        self.dom = dom
+        self.registerChannel()
+        #
+        #if xend.blkif.be_port:
+        #    xend.blkif.recovery = True
+        #xend.blkif.be_port = xend.main.port_from_dom(dom)
+
+    def getControlDomain(self):
+        return self.dom
+
+    def reattachDevice(self, dom, vdev):
+        blkif = self.getInstanceByDom(dom)
+        if blkif:
+            blkif.reattachDevice(vdev)
+        self.attached = self.devicesAttached()
+        if self.attached:
+            self.reattached()
+
+    def devicesAttached(self):
+        """Check if all devices are attached.
+        """
+        attached = 1
+        for blkif in self.getInstances():
+            if not blkif.attached:
+                attached = 0
+                break
+        return attached
+                         
+    def reattached(self):
+        for blkif in self.getInstances():
+            blkif.reattached()
+
+    def recv_be_create(self, msg, req):
+        #print 'recv_be_create>'
+        val = unpackMsg('blkif_be_create_t', msg)
+        blkif = self.getInstanceByDom(val['domid'])
+        self.callDeferred(blkif)
+    
+    def recv_be_connect(self, msg, req):
+        #print 'recv_be_create>'
+        val = unpackMsg('blkif_be_connect_t', msg)
+        blkif = self.getInstanceByDom(val['domid'])
+        if blkif:
+            blkif.send_fe_interface_status_changed()
+        else:
+            pass
+    
+    def recv_be_vbd_create(self, msg, req):
+        #print 'recv_be_vbd_create>'
+        val = unpackMsg('blkif_be_vbd_create_t', msg)
+        blkif = self.getInstanceByDom(val['domid'])
+        if blkif:
+            blkif.send_be_vbd_grow(val['vdevice'])
+        else:
+            pass
+    
+    def recv_be_vbd_grow(self, msg, req):
+        #print 'recv_be_vbd_grow>'
+        val = unpackMsg('blkif_be_vbd_grow_t', msg)
+        # Check status?
+        if self.attached:
+            self.callDeferred(0)
+        else:
+            self.reattachDevice(val['domid'], val['vdevice'])
+
+    def recv_be_driver_status_changed(self, msg, req):
+        val = unpackMsg('blkif_be_driver_status_changed_t', msg)
+        status = val['status']
+        if status == BLKIF_DRIVER_STATUS_UP and not self.attached:
+            for blkif in self.getInstances():
+                blkif.detach()
+
+class BlkDev(controller.Dev):
+    """Info record for a block device.
+    """
+
+    def __init__(self, ctrl, vdev, mode, segment):
+        controller.Dev.__init__(self, ctrl)
+        self.vdev = vdev
+        self.mode = mode
+        self.device = segment['device']
+        self.start_sector = segment['start_sector']
+        self.nr_sectors = segment['nr_sectors']
+        self.attached = 1
+
+    def readonly(self):
+        return 'w' not in self.mode
+
+    def sxpr(self):
+        val = ['blkdev', ['vdev', self.vdev], ['mode', self.mode] ]
+        return val
+
+    def destroy(self):
+        print 'BlkDev>destroy>', self.vdev
+        PrettyPrint.prettyprint(self.sxpr())
+        self.controller.send_be_vbd_destroy(self.vdev)
+        
+class BlkifController(controller.Controller):
+    """Block device interface controller. Handles all block devices
+    for a domain.
+    """
+    
+    def __init__(self, factory, dom):
+        #print 'BlkifController> dom=', dom
+        controller.Controller.__init__(self, factory, dom)
+        self.devices = {}
+
+        self.majorTypes = [ CMSG_BLKIF_FE ]
+
+        self.subTypes = {
+            CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
+                self.recv_fe_driver_status_changed,
+            CMSG_BLKIF_FE_INTERFACE_CONNECT    :
+                self.recv_fe_interface_connect,
+            }
+        self.attached = 1
+        self.evtchn = None
+        self.registerChannel()
+        #print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx
+
+    def sxpr(self):
+        val = ['blkif', ['dom', self.dom]]
+        if self.evtchn:
+            val.append(['evtchn',
+                        self.evtchn['port1'],
+                        self.evtchn['port2']])
+        return val
+
+    def lostChannel(self):
+        print 'BlkifController>lostChannel>', 'dom=', self.dom
+        #self.destroyDevices()
+        controller.Controller.lostChannel(self)
+
+    def getDevices(self):
+        return self.devices.values()
+
+    def getDevice(self, vdev):
+        return self.devices.get(vdev)
+
+    def addDevice(self, vdev, mode, segment):
+        if vdev in self.devices: return None
+        dev = BlkDev(self, vdev, mode, segment)
+        self.devices[vdev] = dev
+        return dev
+
+    def attachDevice(self, vdev, mode, segment, recreate=0):
+        """Attach a device to the specified interface.
+        """
+        #print 'BlkifController>attach_device>', self.dom, vdev, mode, segment
+        dev = self.addDevice(vdev, mode, segment)
+        if not dev: return -1
+        if recreate:
+            d = defer.Deferred()
+            d.callback(self)
+        else:
+            self.send_be_vbd_create(vdev)
+            d = self.factory.addDeferred()
+        return d
+
+    def destroy(self):
+        print 'BlkifController>destroy> dom=', self.dom
+        def cb_destroy(val):
+            self.send_be_destroy()
+        d = self.factory.addDeferred()
+        d.addCallback(cb_destroy)
+        self.send_be_disconnect()
+        #self.destroyDevices()
+
+    def destroyDevices(self):
+        for dev in self.getDevices():
+            dev.destroy()
+
+    def detach(self):
+        """Detach all devices, when the back-end control domain has changed.
+        """
+        self.attached = 0
+        for dev in self.devices.values():
+            dev.attached = 0
+            self.send_be_vbd_create(vdev)
+
+    def reattachDevice(self, vdev):
+        """Reattach a device, when the back-end control domain has changed.
+        """
+        dev = self.devices[vdev]
+        dev.attached = 1
+        attached = 1
+        for dev in self.devices.values():
+            if not dev.attached:
+                attached = 0
+                break
+        self.attached = attached
+        return self.attached
+
+    def reattached(self):
+        """All devices have been reattached after the back-end control
+        domain has changed.
+        """
+        msg = packMsg('blkif_fe_interface_status_changed_t',
+                      { 'handle' : 0,
+                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED})
+        self.writeRequest(msg)
+
+    def recv_fe_driver_status_changed(self, msg, req):
+        msg = packMsg('blkif_fe_interface_status_changed_t',
+                      { 'handle' : 0,
+                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
+                        'evtchn' : 0 })
+        self.writeRequest(msg)
+    
+    def recv_fe_interface_connect(self, msg, req):
+        val = unpackMsg('blkif_fe_interface_connect_t', msg)
+        self.evtchn = channel.eventChannel(0, self.dom)
+        print 'recv_fe_interface_connect>'
+        PrettyPrint.prettyprint(self.sxpr())
+        msg = packMsg('blkif_be_connect_t',
+                      { 'domid'        : self.dom,
+                        'blkif_handle' : val['handle'],
+                        'evtchn'       : self.evtchn['port1'],
+                        'shmem_frame'  : val['shmem_frame'] })
+        self.factory.writeRequest(msg)
+        pass
+
+    #def recv_fe_interface_status_changed(self, msg, req):
+    #    (hnd, status, chan) = unpackMsg('blkif_fe_interface_status_changed_t', msg)
+    #    print 'recv_fe_interface_status_changed>', hnd, status, chan
+    #   pass
+
+    def send_fe_interface_status_changed(self):
+        msg = packMsg('blkif_fe_interface_status_changed_t',
+                      { 'handle' : 0,
+                        'status' : BLKIF_INTERFACE_STATUS_CONNECTED,
+                        'evtchn' : self.evtchn['port2'] })
+        self.writeRequest(msg)
+
+    def send_be_create(self):
+        msg = packMsg('blkif_be_create_t',
+                      { 'domid'        : self.dom,
+                        'blkif_handle' : 0 })
+        self.factory.writeRequest(msg)
+
+    def send_be_disconnect(self):
+        print '>BlkifController>send_be_disconnect>', 'dom=', self.dom
+        msg = packMsg('blkif_be_disconnect_t',
+                      { 'domid'        : self.dom,
+                        'blkif_handle' : 0 })
+        self.factory.writeRequest(msg)
+
+    def send_be_destroy(self):
+        print '>BlkifController>send_be_destroy>', 'dom=', self.dom
+        msg = packMsg('blkif_be_destroy_t',
+                      { 'domid'        : self.dom,
+                        'blkif_handle' : 0 })
+        self.factory.writeRequest(msg)
+
+    def send_be_vbd_create(self, vdev):
+        dev = self.devices[vdev]
+        msg = packMsg('blkif_be_vbd_create_t',
+                      { 'domid'        : self.dom,
+                        'blkif_handle' : 0,
+                        'vdevice'      : dev.vdev,
+                        'readonly'     : dev.readonly() })
+        self.factory.writeRequest(msg)
+        
+    def send_be_vbd_grow(self, vdev):
+        dev = self.devices[vdev]
+        msg = packMsg('blkif_be_vbd_grow_t',
+                      { 'domid'                : self.dom,
+                        'blkif_handle'         : 0,
+                        'vdevice'              : dev.vdev,
+                        'extent.device'        : dev.device,
+                        'extent.sector_start'  : dev.start_sector,
+                        'extent.sector_length' : dev.nr_sectors })
+        self.factory.writeRequest(msg)
+
+    def send_be_vbd_destroy(self, vdev):
+        print '>BlkifController>send_be_vbd_destroy>', 'dom=', self.dom, 'vdev=', vdev
+        PrettyPrint.prettyprint(self.sxpr())
+        dev = self.devices[vdev]
+        msg = packMsg('blkif_be_vbd_destroy_t',
+                      { 'domid'                : self.dom,
+                        'blkif_handle'         : 0,
+                        'vdevice'              : dev.vdev })
+        del self.devices[vdev]
+        self.factory.writeRequest(msg)
+    
diff --git a/tools/xen/lib/xend/server/channel.py b/tools/xen/lib/xend/server/channel.py
new file mode 100755 (executable)
index 0000000..be98a37
--- /dev/null
@@ -0,0 +1,378 @@
+import xen.ext.xc; xc = xen.ext.xc.new()
+from xen.ext import xu
+from messages import msgTypeName
+
+VIRQ_MISDIRECT  = 0  # Catch-all interrupt for unbound VIRQs.
+VIRQ_TIMER      = 1  # Timebase update, and/or requested timeout.
+VIRQ_DEBUG      = 2  # Request guest to dump debug info.
+VIRQ_CONSOLE    = 3  # (DOM0) bytes received on emergency console.
+VIRQ_DOM_EXC    = 4  # (DOM0) Exceptional event for some domain.
+
+def eventChannel(dom1, dom2):
+    return xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2)
+
+class ChannelFactory:
+    """Factory for creating channels.
+    Maintains a table of channels.
+    """
+
+    """ Channels indexed by index. """
+    channels = {}
+
+    def __init__(self):
+        """Constructor - do not use. Use the channelFactory function."""
+        self.notifier = xu.notifier()
+    
+    def addChannel(self, channel):
+        """Add a channel.
+        """
+        idx = channel.idx
+        self.channels[idx] = channel
+        self.notifier.bind(idx)
+        # Try to wake it up
+        #self.notifier.unmask(idx)
+        #channel.notify()
+
+    def getChannel(self, idx):
+        """Get the channel with the given index (if any).
+        """
+        return self.channels.get(idx)
+
+    def delChannel(self, idx):
+        """Remove the channel with the given index (if any).
+        """
+        if idx in self.channels:
+            del self.channels[idx]
+            self.notifier.unbind(idx)
+
+    def domChannel(self, dom):
+        """Get the channel for the given domain.
+        Construct if necessary.
+        """
+        dom = int(dom)
+        for chan in self.channels.values():
+            if not isinstance(chan, Channel): continue
+            if chan.dom == dom:
+                return chan
+        chan = Channel(self, dom)
+        self.addChannel(chan)
+        return chan
+
+    def virqChannel(self, virq):
+        """Get the channel for the given virq.
+        Construct if necessary.
+        """
+        for chan in self.channels.values():
+            if not isinstance(chan, VirqChannel): continue
+            if chan.virq == virq:
+                return chan
+        chan = VirqChannel(self, virq)
+        self.addChannel(chan)
+        return chan
+
+    def channelClosed(self, channel):
+        """The given channel has been closed - remove it.
+        """
+        self.delChannel(channel.idx)
+
+    def createPort(self, dom):
+        """Create a port for a channel to the given domain.
+        """
+        return xu.port(dom)
+
+def channelFactory():
+    """Singleton constructor for the channel factory.
+    Use this instead of the class constructor.
+    """
+    global inst
+    try:
+        inst
+    except:
+        inst = ChannelFactory()
+    return inst
+
+class BaseChannel:
+    """Abstract superclass for channels.
+
+    The subclass constructor must set idx to the port to use.
+    """
+
+    def __init__(self, factory):
+        self.factory = factory
+        self.idx = -1
+        self.closed = 0
+
+    def getIndex(self):
+        """Get the channel index.
+        """
+        return self.idx
+
+    def notificationReceived(self, type):
+        """Called when a notification is received.
+        Closes the channel on error, otherwise calls
+        handleNotification(type), which should be defined
+        in a subclass.
+        """
+        #print 'notificationReceived> type=', type, self
+        if self.closed: return
+        if type == self.factory.notifier.EXCEPTION:
+            print 'notificationReceived> EXCEPTION'
+            info = xc.evtchn_status(self.idx)
+            if info['status'] == 'unbound':
+                print 'notificationReceived> EXCEPTION closing...'
+                self.close()
+                return
+        self.handleNotification(type)
+
+    def close(self):
+        """Close the channel. Calls channelClosed() on the factory.
+        Override in subclass.
+        """
+        self.factory.channelClosed(self)
+
+    def handleNotification(self, type):
+        """Handle notification.
+        Define in subclass.
+        """
+        pass
+        
+
+class VirqChannel(BaseChannel):
+    """A channel for handling a virq.
+    """
+    
+    def __init__(self, factory, virq):
+        """Create a channel for the given virq using the given factory.
+
+        Do not call directly, use virqChannel on the factory.
+        """
+        BaseChannel.__init__(self, factory)
+        self.virq = virq
+        # Notification port (int).
+        self.port = xc.evtchn_bind_virq(virq)
+        self.idx = self.port
+        # Clients to call when a virq arrives.
+        self.clients = []
+
+    def __repr__(self):
+        return ('<VirqChannel virq=%d port=%d>'
+                % (self.virq, self.port))
+
+    def getVirq(self):
+        """Get the channel's virq.
+        """
+        return self.virq
+
+    def close(self):
+        """Close the channel. Calls lostChannel(self) on all its clients and
+        channelClosed() on the factory.
+        """
+        for c in self.clients:
+            c.lostChannel(self)
+        del self.clients
+        BaseChannel.close(self)
+
+    def registerClient(self, client):
+        """Register a client. The client will be called with
+        client.virqReceived(virq) when a virq is received.
+        The client will be called with client.lostChannel(self) if the
+        channel is closed.
+        """
+        self.clients.append(client)
+
+    def handleNotification(self, type):
+        for c in self.clients:
+            c.virqReceived(self.virq)
+
+    def notify(self):
+        xc.evtchn_send(self.port)
+
+
+class Channel(BaseChannel):
+    """A control channel to a domain. Messages for the domain device controllers
+    are multiplexed over the channel (console, block devs, net devs).
+    """
+
+    def __init__(self, factory, dom):
+        """Create a channel to the given domain using the given factory.
+
+        Do not call directly, use domChannel on the factory.
+        """
+        BaseChannel.__init__(self, factory)
+        # Domain.
+        self.dom = int(dom)
+        # Domain port (object).
+        self.port = self.factory.createPort(dom)
+        # Channel port (int).
+        self.idx = self.port.local_port
+        # Registered devices.
+        self.devs = []
+        # Devices indexed by the message types they handle.
+        self.devs_by_type = {}
+        # Output queue.
+        self.queue = []
+        self.closed = 0
+
+    def getLocalPort(self):
+        """Get the local port.
+        """
+        return self.port.local_port
+
+    def getRemotePort(self):
+        """Get the remote port.
+        """
+        return self.port.remote_port
+
+    def close(self):
+        """Close the channel. Calls lostChannel() on all its devices and
+        channelClosed() on the factory.
+        """
+        self.closed = 1
+        for d in self.devs:
+            d.lostChannel()
+        self.factory.channelClosed(self)
+        self.devs = []
+        self.devs_by_type = {}
+
+    def registerDevice(self, types, dev):
+        """Register a device controller.
+
+        @param types message types the controller handles
+        @param dev   device controller
+        """
+        if self.closed: return
+        self.devs.append(dev)
+        for ty in types:
+            self.devs_by_type[ty] = dev
+
+    def deregisterDevice(self, dev):
+        """Remove the registration for a device controller.
+
+        @param dev device controller
+        """
+        if dev in self.devs:
+            self.devs.remove(dev)
+        types = [ ty for (ty, d) in self.devs_by_type.items() if d == dev ]
+        for ty in types:
+            del self.devs_by_type[ty]
+
+    def getDevice(self, type):
+        """Get the device controller handling a message type.
+
+        @param type message type
+        @returns controller or None
+        """
+        return self.devs_by_type.get(type)
+
+    def getMessageType(self, msg):
+        """Get a 2-tuple of the message type and subtype.
+        """
+        hdr = msg.get_header()
+        return (hdr['type'], hdr.get('subtype'))
+
+    def __repr__(self):
+        return ('<Channel dom=%d ports=%d:%d>'
+                % (self.dom,
+                   self.port.local_port,
+                   self.port.remote_port))
+
+    def handleNotification(self, type):
+        work = 0
+        work += self.handleRequests()
+        work += self.handleResponses()
+        work += self.handleWrites()
+        if work:
+            self.notify()
+
+    def notify(self):
+        self.port.notify()
+
+    def handleRequests(self):
+        work = 0
+        while 1:
+            msg = self.readRequest()
+            if not msg: break
+            self.requestReceived(msg)
+            work += 1
+        return work
+
+    def requestReceived(self, msg):
+        (ty, subty) = self.getMessageType(msg)
+        #todo:  Must respond before writing any more messages.
+        #todo:  Should automate this (respond on write)
+        self.port.write_response(msg)
+        dev = self.getDevice(ty)
+        if dev:
+            dev.requestReceived(msg, ty, subty)
+        else:
+            print ("requestReceived> No device: Message type %s %d:%d"
+                   % (msgTypeName(ty, subty), ty, subty)), self
+
+    def handleResponses(self):
+        work = 0
+        while 1:
+            msg = self.readResponse()
+            if not msg: break
+            self.responseReceived(msg)
+            work += 1
+        return work
+
+    def responseReceived(self, msg):
+        (ty, subty) = self.getMessageType(msg)
+        dev = self.getDevice(ty)
+        if dev:
+            dev.responseReceived(msg, ty, subty)
+        else:
+            print ("responseReceived> No device: Message type %d:%d"
+                   % (msgTypeName(ty, subty), ty, subty)), self
+
+    def handleWrites(self):
+        work = 0
+        # Pull data from producers.
+        for dev in self.devs:
+            work += dev.produceRequests()
+        # Flush the queue.
+        while self.queue and self.port.space_to_write_request():
+            msg = self.queue.pop(0)
+            self.port.write_request(msg)
+            work += 1
+        return work
+
+    def writeRequest(self, msg, notify=1):
+        if self.closed:
+            val = -1
+        elif self.writeReady():
+            self.port.write_request(msg)
+            if notify: self.notify()
+            val = 1
+        else:
+            self.queue.append(msg)
+            val = 0
+        return val
+
+    def writeResponse(self, msg):
+        if self.closed: return -1
+        self.port.write_response(msg)
+        return 1
+
+    def writeReady(self):
+        if self.closed or self.queue: return 0
+        return self.port.space_to_write_request()
+
+    def readRequest(self):
+        if self.closed:
+            return None
+        if self.port.request_to_read():
+            val = self.port.read_request()
+        else:
+            val = None
+        return val
+        
+    def readResponse(self):
+        if self.closed:
+            return None
+        if self.port.response_to_read():
+            val = self.port.read_response()
+        else:
+            val = None
+        return val
diff --git a/tools/xen/lib/xend/server/console.py b/tools/xen/lib/xend/server/console.py
new file mode 100755 (executable)
index 0000000..75793d3
--- /dev/null
@@ -0,0 +1,230 @@
+
+from twisted.internet import reactor
+from twisted.internet import protocol
+from twisted.protocols import telnet
+
+from xen.ext import xu
+
+from xen.xend import EventServer
+eserver = EventServer.instance()
+
+import controller
+from messages import *
+from params import *
+
+"""Telnet binary option."""
+TRANSMIT_BINARY = '0'
+WILL = chr(251)
+IAC = chr(255)
+
+class ConsoleProtocol(protocol.Protocol):
+    """Asynchronous handler for a console TCP socket.
+    """
+
+    def __init__(self, controller, idx):
+        self.controller = controller
+        self.idx = idx
+        self.addr = None
+        self.binary = 0
+
+    def connectionMade(self):
+        peer = self.transport.getPeer()
+        self.addr = (peer.host, peer.port)
+        if self.controller.connect(self.addr, self):
+            self.transport.write("Cannot connect to console %d on domain %d\n"
+                                 % (self.idx, self.controller.dom))
+            self.loseConnection()
+            return
+        else:
+            self.transport.write("Connected to console %d on domain %d\n"
+                                 % (self.idx, self.controller.dom))
+            self.setTelnetTransmitBinary()
+            eserver.inject('xend.console.connect',
+                           [self.idx, self.addr[0], self.addr[1]])
+
+    def setTelnetTransmitBinary(self):
+        """Send the sequence to set the telnet TRANSMIT-BINARY option.
+        """
+        self.write(IAC + WILL + TRANSMIT_BINARY)
+
+    def dataReceived(self, data):
+        if self.controller.handleInput(self, data):
+            self.loseConnection()
+
+    def write(self, data):
+        #if not self.connected: return -1
+        self.transport.write(data)
+        return len(data)
+
+    def connectionLost(self, reason=None):
+        eserver.inject('xend.console.disconnect',
+                       [self.idx, self.addr[0], self.addr[1]])
+        self.controller.disconnect()
+
+    def loseConnection(self):
+        self.transport.loseConnection()
+
+class ConsoleFactory(protocol.ServerFactory):
+    """Asynchronous handler for a console server socket.
+    """
+    protocol = ConsoleProtocol
+    
+    def __init__(self, controller, idx):
+        #protocol.ServerFactory.__init__(self)
+        self.controller = controller
+        self.idx = idx
+
+    def buildProtocol(self, addr):
+        proto = self.protocol(self.controller, self.idx)
+        proto.factory = self
+        return proto
+
+class ConsoleControllerFactory(controller.ControllerFactory):
+    """Factory for creating console controllers.
+    """
+
+    def createInstance(self, dom, console_port=None):
+        if console_port is None:
+            console_port = CONSOLE_PORT_BASE + dom
+        console = ConsoleController(self, dom, console_port)
+        self.addInstance(console)
+        eserver.inject('xend.console.create',
+                       [console.idx, console.dom, console.console_port])
+        return console
+        
+    def consoleClosed(self, console):
+        eserver.inject('xend.console.close', console.idx)
+        self.delInstance(console)
+
+class ConsoleController(controller.Controller):
+    """Console controller for a domain.
+    Does not poll for i/o itself, but relies on the notifier to post console
+    output and the connected TCP sockets to post console input.
+    """
+
+    def __init__(self, factory, dom, console_port):
+        #print 'ConsoleController> dom=', dom, type(dom)
+        controller.Controller.__init__(self, factory, dom)
+        self.majorTypes = [ CMSG_CONSOLE ]
+        self.status = "new"
+        self.addr = None
+        self.conn = None
+        self.rbuf = xu.buffer()
+        self.wbuf = xu.buffer()
+        self.console_port = console_port
+
+        self.registerChannel()
+        self.listener = None
+        self.listen()
+        #print 'ConsoleController<', 'dom=', self.dom, 'idx=', self.idx
+
+    def sxpr(self):
+        val =['console',
+              ['status',       self.status ],
+              ['id',           self.idx ],
+              ['domain',       self.dom ],
+              ['local_port',   self.channel.getLocalPort() ],
+              ['remote_port',  self.channel.getRemotePort() ],
+              ['console_port', self.console_port ] ]
+        if self.addr:
+            val.append(['connected', self.addr[0], self.addr[1]])
+        return val
+
+    def ready(self):
+        return not (self.closed() or self.rbuf.empty())
+
+    def closed(self):
+        return self.status == 'closed'
+
+    def connected(self):
+        return self.status == 'connected'
+
+    def close(self):
+        try:
+            #print 'ConsoleController> close dom=', self.dom
+            self.status = "closed"
+            if self.conn:
+                self.conn.loseConnection()
+            self.listener.stopListening()
+            self.deregisterChannel()
+            self.lostChannel()
+        except Exception, ex:
+            print 'ConsoleController>close>', ex
+            raise
+
+    def listen(self):
+        """Listen for TCP connections to the console port..
+        """
+        if self.closed(): return
+        self.status = "listening"
+        if self.listener:
+            #self.listener.startListening()
+            pass
+        else:
+            f = ConsoleFactory(self, self.idx)
+            self.listener = reactor.listenTCP(self.console_port, f)
+
+    def connect(self, addr, conn):
+        if self.closed(): return -1
+        if self.connected(): return -1
+        self.addr = addr
+        self.conn = conn
+        self.status = "connected"
+        self.handleOutput()
+        return 0
+
+    def disconnect(self):
+        if self.conn:
+            self.conn.loseConnection()
+        self.addr = None
+        self.conn = None
+        self.listen()
+
+    def requestReceived(self, msg, type, subtype):
+        #print '***Console', self.dom, msg.get_payload()
+        self.rbuf.write(msg.get_payload())
+        self.handleOutput()
+        
+    def responseReceived(self, msg, type, subtype):
+        pass
+
+    def produceRequests(self):
+        # Send as much pending console data as there is room for.
+        work = 0
+        while not self.wbuf.empty() and self.channel.writeReady():
+            msg = xu.message(CMSG_CONSOLE, 0, 0)
+            msg.append_payload(self.wbuf.read(msg.MAX_PAYLOAD))
+            work += self.channel.writeRequest(msg, notify=0)
+        return work
+
+    def handleInput(self, conn, data):
+        """Handle some external input aimed at the console.
+        Called from a TCP connection (conn).
+        """
+        if self.closed(): return -1
+        if conn != self.conn: return 0
+        self.wbuf.write(data)
+        if self.produceRequests():
+            self.channel.notify()
+        return 0
+
+    def handleOutput(self):
+        """Handle buffered output from the console.
+        Sends it to the connected console (if any).
+        """
+        if self.closed():
+            #print 'Console>handleOutput> closed'
+            return -1
+        if not self.conn:
+            #print 'Console>handleOutput> not connected'
+            return 0
+        while not self.rbuf.empty():
+            try:
+                #print 'Console>handleOutput> writing...'
+                bytes = self.conn.write(self.rbuf.peek())
+                if bytes > 0:
+                    self.rbuf.discard(bytes)
+            except socket.error, error:
+                pass
+        #print 'Console>handleOutput<'
+        return 0
diff --git a/tools/xen/lib/xend/server/controller.py b/tools/xen/lib/xend/server/controller.py
new file mode 100755 (executable)
index 0000000..900c2d5
--- /dev/null
@@ -0,0 +1,169 @@
+from twisted.internet import defer
+
+import channel
+from messages import msgTypeName
+
+class CtrlMsgRcvr:
+    """Abstract class for things that deal with a control interface to a domain.
+    """
+
+
+    def __init__(self):
+        self.channelFactory = channel.channelFactory()
+        self.majorTypes = [ ]
+        self.subTypes = {}
+        self.dom = None
+        self.channel = None
+        self.idx = None
+
+    def requestReceived(self, msg, type, subtype):
+        method = self.subTypes.get(subtype)
+        if method:
+            method(msg, 1)
+        else:
+            print ('requestReceived> No handler: Message type %s %d:%d'
+                   % (msgTypeName(type, subtype), type, subtype)), self
+        
+    def responseReceived(self, msg, type, subtype):
+        method = self.subTypes.get(subtype)
+        if method:
+            method(msg, 0)
+        else:
+            print ('responseReceived> No handler: Message type %s %d:%d'
+                   % (msgTypeName(type, subtype), type, subtype)), self
+
+    def lostChannel(self):
+        pass
+    
+    def registerChannel(self):
+        #print 'CtrlMsgRcvr>registerChannel>', self
+        self.channel = self.channelFactory.domChannel(self.dom)
+        self.idx = self.channel.getIndex()
+        if self.majorTypes:
+            self.channel.registerDevice(self.majorTypes, self)
+        
+    def deregisterChannel(self):
+        #print 'CtrlMsgRcvr>deregisterChannel>', self
+        if self.channel:
+            self.channel.deregisterDevice(self)
+            del self.channel
+
+    def produceRequests(self):
+        return 0
+
+    def writeRequest(self, msg):
+        if self.channel:
+            self.channel.writeRequest(msg)
+        else:
+            print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self
+
+    def writeResponse(self, msg):
+        if self.channel:
+            self.channel.writeResponse(msg)
+        else:
+            print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self
+            
+class ControllerFactory(CtrlMsgRcvr):
+    """Abstract class for factories creating controllers.
+    Maintains a table of instances.
+    """
+
+    def __init__(self):
+        CtrlMsgRcvr.__init__(self)
+        self.instances = {}
+        self.dlist = []
+        self.dom = 0
+        # Timeout (in seconds) for deferreds.
+        self.timeout = 10
+        
+    def addInstance(self, instance):
+        self.instances[instance.idx] = instance
+
+    def getInstance(self, idx):
+        return self.instances.get(idx)
+
+    def getInstances(self):
+        return self.instances.values()
+
+    def getInstanceByDom(self, dom):
+        for inst in self.instances.values():
+            if inst.dom == dom:
+                return inst
+        return None
+
+    def delInstance(self, instance):
+        #print 'ControllerFactory>delInstance>', instance.idx
+        if instance.idx in self.instances:
+            #print 'ControllerFactory>delInstance> remove', instance.idx
+            del self.instances[instance.idx]
+
+    def createInstance(self, dom, recreate=0):
+        raise NotImplementedError()
+
+    def instanceClosed(self, instance):
+        #print 'ControllerFactory>instanceClosed>', instance.idx, instance
+        self.delInstance(instance)
+
+    def addDeferred(self):
+        d = defer.Deferred()
+        if self.timeout > 0:
+            # The deferred will error if not called before timeout.
+            d.setTimeout(self.timeout)
+        self.dlist.append(d)
+        return d
+
+    def callDeferred(self, *args):
+        if self.dlist:
+            d = self.dlist.pop(0)
+            d.callback(*args)
+
+    def errDeferred(self, *args):
+        if self.dlist:
+            d = self.dlist.pop(0)
+            d.errback(*args)
+
+class Controller(CtrlMsgRcvr):
+    """Abstract class for a device controller attached to a domain.
+    """
+
+    def __init__(self, factory, dom):
+        CtrlMsgRcvr.__init__(self)
+        self.factory = factory
+        self.dom = int(dom)
+        self.channel = None
+        self.idx = None
+
+    def close(self):
+        self.deregisterChannel()
+        self.lostChannel()
+
+    def lostChannel(self):
+        #print 'Controller>lostChannel>', self, self.factory
+        self.factory.instanceClosed(self)
+
+class Dev:
+
+    def __init__(self, controller):
+        self.controller = controller
+        self.props = {}
+
+    def setprop(self, k, v):
+        self.props[k] = v
+
+    def getprop(self, k, v=None):
+        return self.props.get(k, v)
+
+    def hasprop(self, k):
+        return k in self.props
+
+    def delprop(self, k):
+        if k in self.props:
+            del self.props[k]
+
+    #def __repr__(self):
+    #    return str(self.sxpr())
+
+    def sxpr(self):
+        raise NotImplementedError()
+
+    
diff --git a/tools/xen/lib/xend/server/cstruct.py b/tools/xen/lib/xend/server/cstruct.py
new file mode 100755 (executable)
index 0000000..880931b
--- /dev/null
@@ -0,0 +1,269 @@
+import struct
+
+class Struct:
+
+    maxDepth = 10
+
+    base = ['x', 'B', 'H', 'I', 'L', 'Q', 'c', 'h', 'i', 'l', 'q', ]
+
+    sizes = {'B': 1,
+            'H': 2,
+            'I': 4,
+            'L': 4,
+            'Q': 8,
+            'c': 1,
+            'h': 2,
+            'i': 4,
+            'l': 4,
+            'q': 8,
+            'x': 1,
+            }
+
+    formats = {
+        'int8'          : 'B',
+        'int16'         : 'H',
+        'int32'         : 'I',
+        'int64'         : 'Q',
+        'u8'            : 'B',
+        'u16'           : 'H',
+        'u32'           : 'I',
+        'u64'           : 'Q'
+        }
+
+    def typedef(self, name, val):
+        self.formats[name] = val
+
+    def struct(self, name, *f):
+        self.typedef(name, StructInfo(self, f))
+        
+    def getType(self, name):
+        return self.formats[name]
+
+    def format(self, ty):
+        d = 0
+        f = ty
+        while d < self.maxDepth:
+            d += 1
+            f = self.formats[f]
+            if isinstance(f, StructInfo):
+                return f.format()
+            if f in self.base:
+                return f
+        return -1
+
+    def alignedformat(self, ty):
+        fmt = self.format(ty)
+        #print 'alignedformat> %s |%s|' %(ty, fmt)
+        afmt = self.align(fmt)
+        #print 'alignedformat< %s |%s| |%s|' % (ty, fmt, afmt)
+        return afmt
+
+    def align(self, fmt):
+        n1 = 0
+        afmt = ''
+        for a in fmt:
+            n2 = self.getSize(a)
+            m = n1 % n2
+            if m:
+                d = (n2 - m)
+                afmt += 'x' * d
+                n1 += d
+            afmt += a
+            n1 += n2
+        return afmt
+
+    def fmtsize(self, fmt):
+        s = 0
+        for f in fmt:
+            s += self.getSize(f)
+        return s
+
+    def getSize(self, f):
+        return self.sizes[f]
+
+    def pack(self, ty, data):
+        return self.getType(ty).pack(data)
+
+    def unpack(self, ty, data):
+        return self.getType(ty).unpack(data)
+
+    def show(self):
+        l = self.formats.keys()
+        l.sort()
+        for v in l:
+            print "%-35s %-10s %s" % (v, self.format(v), self.alignedformat(v))
+
+
+class StructInfo:
+
+    def __init__(self, s, f):
+        self.fmt = None
+        self.structs = s
+        self.fields = f
+
+    def alignedformat(self):
+        if self.afmt: return self.afmt
+        self.afmt = self.structs.align(self.format())
+        return self.afmt
+    
+    def format(self):
+        if self.fmt: return self.fmt
+        fmt = ""
+        for (ty, name) in self.fields:
+            fmt += self.formatString(ty)
+        self.fmt = fmt
+        return fmt
+
+    def formatString(self, ty):
+        if ty in self.fields:
+            ty = self.fields[ty]
+        return self.structs.format(ty)
+
+    def pack(self, *args):
+        return struct.pack(self.alignedformat(), *args)
+
+    def unpack(self, data):
+        return struct.unpack(self.alignedformat(), data)
+
+types = Struct()
+
+types.typedef('short'         , 'h')
+types.typedef('int'           , 'i')
+types.typedef('long'          , 'l')
+types.typedef('unsigned short', 'H')
+types.typedef('unsigned int'  , 'I')
+types.typedef('unsigned long' , 'L')
+types.typedef('domid_t'       , 'u64')
+types.typedef('blkif_vdev_t'  , 'u16')
+types.typedef('blkif_pdev_t'  , 'u16')
+types.typedef('blkif_sector_t', 'u64')
+
+types.struct('u8[6]',
+             ('u8', 'a1'),
+             ('u8', 'a2'),
+             ('u8', 'a3'),
+             ('u8', 'a4'),
+             ('u8', 'a5'),
+             ('u8', 'a6'))
+             
+types.struct('blkif_fe_interface_status_changed_t',
+    ('unsigned int',    'handle'),
+    ('unsigned int',    'status'),
+    ('unsigned int',    'evtchn'))
+
+types.struct('blkif_fe_driver_status_changed_t',
+    ('unsigned int',    'status'),
+    ('unsigned int',    'nr_interfaces'))
+
+types.struct('blkif_fe_interface_connect_t',
+    ('unsigned int' ,   'handle'),
+    ('unsigned long',   'shmem_frame'))
+
+types.struct('blkif_fe_interface_disconnect_t',
+    ('unsigned int',   'handle'))
+
+types.struct('blkif_extent_t',
+    ('blkif_pdev_t'  , 'device'),
+    ('blkif_sector_t', 'sector_start'),
+    ('blkif_sector_t', 'sector_length'))
+
+types.struct('blkif_be_create_t', 
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'blkif_handle'),
+    ('unsigned int',   'status'))
+             
+types.struct('blkif_be_destroy_t',
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'blkif_handle'),
+    ('unsigned int',   'status'))
+
+types.struct('blkif_be_connect_t',
+    ('domid_t'      ,  'domid'),
+    ('unsigned int' ,  'blkif_handle'),
+    ('unsigned int' ,  'evtchn'),
+    ('unsigned long',  'shmem_frame'),
+    ('unsigned int' ,  'status'))
+
+types.struct('blkif_be_disconnect_t',
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'blkif_handle'),
+    ('unsigned int',   'status'))
+
+types.struct('blkif_be_vbd_create_t', 
+    ('domid_t'     ,   'domid'),         #Q
+    ('unsigned int',   'blkif_handle'),  #I
+    ('blkif_vdev_t',   'vdevice'),       #H
+    ('int'         ,   'readonly'),      #i
+    ('unsigned int',   'status'))        #I
+
+types.struct('blkif_be_vbd_destroy_t', 
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'blkif_handle'),
+    ('blkif_vdev_t',   'vdevice'),
+    ('unsigned int',   'status'))
+
+types.struct('blkif_be_vbd_grow_t', 
+    ('domid_t'       , 'domid'),         #Q
+    ('unsigned int'  , 'blkif_handle'),  #I
+    ('blkif_vdev_t'  , 'vdevice'),       #H   
+    ('blkif_extent_t', 'extent'),        #HQQ
+    ('unsigned int'  , 'status'))        #I
+
+types.struct('blkif_be_vbd_shrink_t', 
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'blkif_handle'),
+    ('blkif_vdev_t',   'vdevice'),
+    ('unsigned int',   'status'))
+
+types.struct('blkif_be_driver_status_changed_t',
+    ('unsigned int',   'status'),
+    ('unsigned int',   'nr_interfaces'))
+
+types.struct('netif_fe_interface_status_changed_t',
+    ('unsigned int',   'handle'),
+    ('unsigned int',   'status'),
+    ('unsigned int',   'evtchn'),
+    ('u8[6]',          'mac'))
+
+types.struct('netif_fe_driver_status_changed_t',
+    ('unsigned int',   'status'),
+    ('unsigned int',   'nr_interfaces'))
+
+types.struct('netif_fe_interface_connect_t',
+    ('unsigned int',   'handle'),
+    ('unsigned long',  'tx_shmem_frame'),
+    ('unsigned long',  'rx_shmem_frame'))
+
+types.struct('netif_fe_interface_disconnect_t',
+    ('unsigned int',   'handle'))
+
+types.struct('netif_be_create_t', 
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'netif_handle'),
+    ('u8[6]'       ,   'mac'),
+    ('unsigned int',   'status'))
+
+types.struct('netif_be_destroy_t',
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'netif_handle'),
+    ('unsigned int',   'status'))
+
+types.struct('netif_be_connect_t', 
+    ('domid_t'      ,  'domid'),
+    ('unsigned int' ,  'netif_handle'),
+    ('unsigned int' ,  'evtchn'),
+    ('unsigned long',  'tx_shmem_frame'),
+    ('unsigned long',  'rx_shmem_frame'),
+    ('unsigned int' ,  'status'))
+
+types.struct('netif_be_disconnect_t',
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'netif_handle'),
+    ('unsigned int',   'status'))
+
+types.struct('netif_be_driver_status_changed_t',
+    ('unsigned int',   'status'),
+    ('unsigned int',   'nr_interfaces'))
+
+if 1 or __name__ == "__main__":
+    types.show()
diff --git a/tools/xen/lib/xend/server/domain.py b/tools/xen/lib/xend/server/domain.py
new file mode 100644 (file)
index 0000000..ab22234
--- /dev/null
@@ -0,0 +1,41 @@
+import channel
+import controller
+from messages import *
+
+class DomainControllerFactory(controller.ControllerFactory):
+    """Factory for creating domain controllers.
+    """
+
+    def createInstance(self, dom):
+        d = DomainController(self, dom)
+        self.addInstance(d)
+        return d
+    
+    def getInstanceByDom(self, dom):
+        for inst in self.instances.values():
+            if inst.dom == dom:
+                return inst
+        inst = self.createInstance(dom)
+        return inst
+
+
+class DomainController(controller.Controller):
+    """Generic controller for a domain.
+    """
+
+    reasons = {'poweroff' : 'shutdown_poweroff_t',
+               'reboot'   : 'shutdown_reboot_t',
+               'suspend'  : 'shutdown_suspend_t' }
+
+    def __init__(self, factory, dom):
+        controller.Controller.__init__(self, factory, dom)
+        self.majorTypes = [ CMSG_SHUTDOWN ]
+        self.registerChannel()
+        print 'DomainController>', self, self.channel, self.idx
+
+    def shutdown(self, reason):
+        msgtype = self.reasons.get(reason)
+        if not msgtype:
+            raise ValueError('invalid reason:' + reason)
+        msg = packMsg(msgtype, {})
+        self.writeRequest(msg)
diff --git a/tools/xen/lib/xend/server/messages.py b/tools/xen/lib/xend/server/messages.py
new file mode 100644 (file)
index 0000000..e12d7b6
--- /dev/null
@@ -0,0 +1,219 @@
+import struct
+
+from xen.ext import xu
+
+DEBUG = 0
+
+""" All message formats.
+Added to incrementally for the various message types.
+See below.
+"""
+msg_formats = {}
+
+#============================================================================
+# Console message types.
+#============================================================================
+
+CMSG_CONSOLE  = 0
+
+console_formats = { 'console_data': (CMSG_CONSOLE, 0) }
+
+msg_formats.update(console_formats)
+
+#============================================================================
+# Block interface message types.
+#============================================================================
+
+CMSG_BLKIF_BE = 1
+CMSG_BLKIF_FE = 2
+
+CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
+CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
+CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
+CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
+
+CMSG_BLKIF_BE_CREATE      = 0
+CMSG_BLKIF_BE_DESTROY     = 1
+CMSG_BLKIF_BE_CONNECT     = 2
+CMSG_BLKIF_BE_DISCONNECT  = 3
+CMSG_BLKIF_BE_VBD_CREATE  = 4
+CMSG_BLKIF_BE_VBD_DESTROY = 5
+CMSG_BLKIF_BE_VBD_GROW    = 6
+CMSG_BLKIF_BE_VBD_SHRINK  = 7
+CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED    = 32
+
+BLKIF_DRIVER_STATUS_DOWN  = 0
+BLKIF_DRIVER_STATUS_UP    = 1
+
+BLKIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
+BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
+BLKIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
+
+BLKIF_BE_STATUS_OKAY                = 0
+BLKIF_BE_STATUS_ERROR               = 1
+BLKIF_BE_STATUS_INTERFACE_EXISTS    = 2
+BLKIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
+BLKIF_BE_STATUS_INTERFACE_CONNECTED = 4
+BLKIF_BE_STATUS_VBD_EXISTS          = 5
+BLKIF_BE_STATUS_VBD_NOT_FOUND       = 6
+BLKIF_BE_STATUS_OUT_OF_MEMORY       = 7
+BLKIF_BE_STATUS_EXTENT_NOT_FOUND    = 8
+BLKIF_BE_STATUS_MAPPING_ERROR       = 9
+
+blkif_formats = {
+    'blkif_be_connect_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT),
+
+    'blkif_be_create_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE),
+
+    'blkif_be_disconnect_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT),
+
+    'blkif_be_destroy_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY),
+
+    'blkif_be_vbd_create_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE),
+
+    'blkif_be_vbd_grow_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW),
+
+    'blkif_be_vbd_destroy_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY),
+
+    'blkif_fe_interface_status_changed_t':
+    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED),
+
+    'blkif_fe_driver_status_changed_t':
+    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED),
+
+    'blkif_fe_interface_connect_t':
+    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT),
+}
+
+msg_formats.update(blkif_formats)
+
+#============================================================================
+# Network interface message types.
+#============================================================================
+
+CMSG_NETIF_BE = 3
+CMSG_NETIF_FE = 4
+
+CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED =  0
+CMSG_NETIF_FE_DRIVER_STATUS_CHANGED    = 32
+CMSG_NETIF_FE_INTERFACE_CONNECT        = 33
+CMSG_NETIF_FE_INTERFACE_DISCONNECT     = 34
+
+CMSG_NETIF_BE_CREATE      = 0
+CMSG_NETIF_BE_DESTROY     = 1
+CMSG_NETIF_BE_CONNECT     = 2
+CMSG_NETIF_BE_DISCONNECT  = 3
+CMSG_NETIF_BE_DRIVER_STATUS_CHANGED    = 32
+
+NETIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
+NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
+NETIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
+
+NETIF_DRIVER_STATUS_DOWN   = 0
+NETIF_DRIVER_STATUS_UP     = 1
+
+netif_formats = {
+    'netif_be_connect_t':
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT),
+
+    'netif_be_create_t':
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE),
+
+    'netif_be_disconnect_t':
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT),
+
+    'netif_be_destroy_t':
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY),
+
+    'netif_be_driver_status_changed_t':
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED),
+
+    'netif_fe_driver_status_changed_t':
+    (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED),
+
+    'netif_fe_interface_connect_t':
+    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT),
+
+    'netif_fe_interface_status_changed_t':
+    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED),
+    }
+
+msg_formats.update(netif_formats)
+
+#============================================================================
+CMSG_SHUTDOWN = 6
+
+CMSG_SHUTDOWN_POWEROFF  = 0
+CMSG_SHUTDOWN_REBOOT    = 1
+CMSG_SHUTDOWN_SUSPEND   = 2
+
+STOPCODE_shutdown       = 0
+STOPCODE_reboot         = 1
+STOPCODE_suspend        = 2
+
+shutdown_formats = {
+    'shutdown_poweroff_t':
+    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_POWEROFF),
+    
+    'shutdown_reboot_t':
+    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_REBOOT),
+
+    'shutdown_suspend_t':
+    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SUSPEND),
+    }
+
+msg_formats.update(shutdown_formats)
+
+#============================================================================
+
+class Msg:
+    pass
+
+def packMsg(ty, params):
+    if DEBUG: print '>packMsg', ty, params
+    (major, minor) = msg_formats[ty]
+    args = {}
+    for (k, v) in params.items():
+        if k == 'mac':
+            for i in range(0, 6):
+                args['mac[%d]' % i] = v[i]
+        else:
+            args[k] = v
+    if DEBUG:
+        for (k, v) in args.items():
+            print 'packMsg>', k, v, type(v)
+    msgid = 0
+    msg = xu.message(major, minor, msgid, args)
+    return msg
+
+def unpackMsg(ty, msg):
+    args = msg.get_payload()
+    mac = [0, 0, 0, 0, 0, 0]
+    macs = []
+    for (k, v) in args.items():
+        if k.startswith('mac['):
+            macs += k
+            i = int(k[4:5])
+            mac[i] = v
+        else:
+            pass
+    if macs:
+        args['mac'] = mac
+        for k in macs:
+            del args[k]
+    if DEBUG: print '<unpackMsg', ty, args
+    return args
+
+def msgTypeName(ty, subty):
+    for (name, info) in msg_formats.items():
+        if info[0] == ty and info[1] == subty:
+            return name
+    return None
+
diff --git a/tools/xen/lib/xend/server/netif.py b/tools/xen/lib/xend/server/netif.py
new file mode 100755 (executable)
index 0000000..01391f7
--- /dev/null
@@ -0,0 +1,304 @@
+import random
+
+from twisted.internet import defer
+
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+from xen.xend import XendBridge
+
+import channel
+import controller
+from messages import *
+
+class NetifControllerFactory(controller.ControllerFactory):
+    """Factory for creating network interface controllers.
+    Also handles the 'back-end' channel to the device driver domain.
+    """
+
+    def __init__(self):
+        controller.ControllerFactory.__init__(self)
+
+        self.majorTypes = [ CMSG_NETIF_BE ]
+
+        self.subTypes = {
+            CMSG_NETIF_BE_CREATE : self.recv_be_create,
+            CMSG_NETIF_BE_CONNECT: self.recv_be_connect,
+            CMSG_NETIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
+            }
+        self.attached = 1
+        self.registerChannel()
+
+    def createInstance(self, dom, recreate=0):
+        """Create or find the network interface controller for a domain.
+        """
+        #print 'netif>createInstance> dom=', dom
+        netif = self.getInstanceByDom(dom)
+        if netif is None:
+            netif = NetifController(self, dom)
+            self.addInstance(netif)
+        return netif
+
+    def getDomainDevices(self, dom):
+        netif = self.getInstanceByDom(dom)
+        return (netif and netif.getDevices()) or []
+
+    def getDomainDevice(self, dom, vif):
+        netif = self.getInstanceByDom(dom)
+        return (netif and netif.getDevice(vif)) or None
+        
+    def setControlDomain(self, dom, recreate=0):
+        """Set the 'back-end' device driver domain.
+        """
+        if self.dom == dom: return
+        self.deregisterChannel()
+        if not recreate:
+            self.attached = 0
+        self.dom = dom
+        self.registerChannel()
+        #
+        #if xend.netif.be_port.remote_dom != 0:
+        #    xend.netif.recovery = True
+        #    xend.netif.be_port = xend.main.port_from_dom(dom)
+        #
+
+    def getControlDomain(self):
+        return self.dom
+
+    def recv_be_create(self, msg, req):
+        self.callDeferred(0)
+    
+    def recv_be_connect(self, msg, req):
+        val = unpackMsg('netif_be_connect_t', msg)
+        dom = val['domid']
+        vif = val['netif_handle']
+        netif = self.getInstanceByDom(dom)
+        if netif:
+            netif.send_interface_connected(vif)
+        else:
+            print "recv_be_connect> unknown vif=", vif
+            pass
+
+    def recv_be_driver_status_changed(self, msg, req):
+        val = unpackMsg('netif_be_driver_status_changed_t', msg)
+        status = val['status']
+        if status == NETIF_DRIVER_STATUS_UP and not self.attached:
+            # If we are not attached the driver domain was changed, and
+            # this signals the new driver domain is ready.
+            for netif in self.getInstances():
+                netif.reattach_devices()
+            self.attached = 1
+
+##         pl = msg.get_payload()
+##         status = pl['status']
+##         if status == NETIF_DRIVER_STATUS_UP:
+##             if xend.netif.recovery:
+##                 print "New netif backend now UP, notifying guests:"
+##                 for netif_key in interface.list.keys():
+##                     netif = interface.list[netif_key]
+##                     netif.create()
+##                     print "  Notifying %d" % netif.dom
+##                     msg = xu.message(
+##                         CMSG_NETIF_FE,
+##                         CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
+##                         { 'handle' : 0, 'status' : 1 })
+##                     netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom),msg)
+##                 print "Done notifying guests"
+##                 recovery = False
+                
+class NetDev(controller.Dev):
+    """Info record for a network device.
+    """
+
+    def __init__(self, ctrl, vif, mac):
+        controller.Dev.__init__(self, ctrl)
+        self.vif = vif
+        self.mac = mac
+        self.evtchn = None
+        self.bridge = None
+
+    def sxpr(self):
+        vif = str(self.vif)
+        mac = ':'.join(map(lambda x: "%x" % x, self.mac))
+        val = ['netdev', ['vif', vif], ['mac', mac]]
+        if self.bridge:
+            val.append(['bridge', self.bridge])
+        if self.evtchn:
+            val.append(['evtchn',
+                        self.evtchn['port1'],
+                        self.evtchn['port2']])
+        return val
+
+    def bridge_add(self, bridge):
+        self.bridge = XendBridge.vif_bridge_add(self.controller.dom, self.vif, bridge)
+
+    def bridge_rem(self):
+        if not self.bridge: return
+        XendBridge.vif_bridge_rem(self.controller.dom, self.vif, self.bridge)
+        self.bridge = None
+
+    def destroy(self):
+        def cb_destroy(val):
+            self.controller.send_be_destroy(self.vif)
+        print 'NetDev>destroy>', 'vif=', self.vif
+        PrettyPrint.prettyprint(self.sxpr())
+        self.bridge_rem()
+        d = self.controller.factory.addDeferred()
+        d.addCallback(cb_destroy)
+        self.controller.send_be_disconnect(self.vif)
+        #self.controller.send_be_destroy(self.vif)
+        
+
+class NetifController(controller.Controller):
+    """Network interface controller. Handles all network devices for a domain.
+    """
+    
+    def __init__(self, factory, dom):
+        #print 'NetifController> dom=', dom
+        controller.Controller.__init__(self, factory, dom)
+        self.devices = {}
+        
+        self.majorTypes = [ CMSG_NETIF_FE ]
+
+        self.subTypes = {
+            CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
+                self.recv_fe_driver_status_changed,
+            CMSG_NETIF_FE_INTERFACE_CONNECT    :
+                self.recv_fe_interface_connect,
+            }
+        self.registerChannel()
+        #print 'NetifController<', 'dom=', self.dom, 'idx=', self.idx
+
+    def sxpr(self):
+        val = ['netif', ['dom', self.dom]]
+        return val
+    
+    def randomMAC(self):
+        # VIFs get a random MAC address with a "special" vendor id.
+        # 
+        # NB. The vendor is currently an "obsolete" one that used to belong
+        # to DEC (AA-00-00). Using it is probably a bit rude :-)
+        # 
+        # NB2. The first bit of the first random octet is set to zero for
+        # all dynamic MAC addresses. This may allow us to manually specify
+        # MAC addresses for some VIFs with no fear of clashes.
+        mac = [ 0xaa, 0x00, 0x00,
+                random.randint(0x00, 0x7f),
+                random.randint(0x00, 0xff),
+                random.randint(0x00, 0xff) ]
+        return mac
+
+    def lostChannel(self):
+        print 'NetifController>lostChannel>', 'dom=', self.dom
+        #self.destroyDevices()
+        controller.Controller.lostChannel(self)
+
+    def getDevices(self):
+        return self.devices.values()
+
+    def getDevice(self, vif):
+        return self.devices.get(vif)
+
+    def addDevice(self, vif, vmac):
+        if vmac is None:
+            mac = self.randomMAC()
+        else:
+            mac = [ int(x, 16) for x in vmac.split(':') ]
+        if len(mac) != 6: raise ValueError("invalid mac")
+        #print "attach_device>", "vif=", vif, "mac=", mac
+        dev = NetDev(self, vif, mac)
+        self.devices[vif] = dev
+        return dev
+
+    def destroy(self):
+        print 'NetifController>destroy>', 'dom=', self.dom
+        self.destroyDevices()
+        
+    def destroyDevices(self):
+        for dev in self.getDevices():
+            dev.destroy()
+
+    def attachDevice(self, vif, vmac, recreate=0):
+        """Attach a network device.
+        If vmac is None a random mac address is assigned.
+
+        @param vif interface index
+        @param vmac mac address (string)
+        """
+        self.addDevice(vif, vmac)
+        if recreate:
+            d = defer.Deferred()
+            d.callback(self)
+        else:
+            d = self.factory.addDeferred()
+            self.send_be_create(vif)
+        return d
+
+    def reattach_devices(self):
+        """Reattach all devices when the back-end control domain has changed.
+        """
+        d = self.factory.addDeferred()
+        self.send_be_create(vif)
+        self.attach_fe_devices(0)
+
+    def attach_fe_devices(self):
+        for dev in self.devices.values():
+            msg = packMsg('netif_fe_interface_status_changed_t',
+                          { 'handle' : dev.vif,
+                            'status' : NETIF_INTERFACE_STATUS_DISCONNECTED,
+                            'evtchn' : 0,
+                            'mac'    : dev.mac })
+            self.writeRequest(msg)
+    
+    def recv_fe_driver_status_changed(self, msg, req):
+        if not req: return
+        msg = packMsg('netif_fe_driver_status_changed_t',
+                      { 'status'        : NETIF_DRIVER_STATUS_UP,
+                        'nr_interfaces' : len(self.devices) })
+        self.writeRequest(msg)
+        self.attach_fe_devices()
+
+    def recv_fe_interface_connect(self, msg, req):
+        val = unpackMsg('netif_fe_interface_connect_t', msg)
+        dev = self.devices[val['handle']]
+        dev.evtchn = channel.eventChannel(0, self.dom)
+        msg = packMsg('netif_be_connect_t',
+                      { 'domid'          : self.dom,
+                        'netif_handle'   : dev.vif,
+                        'evtchn'         : dev.evtchn['port1'],
+                        'tx_shmem_frame' : val['tx_shmem_frame'],
+                        'rx_shmem_frame' : val['rx_shmem_frame'] })
+        self.factory.writeRequest(msg)
+
+    def send_interface_connected(self, vif):
+        dev = self.devices[vif]
+        msg = packMsg('netif_fe_interface_status_changed_t',
+                      { 'handle' : dev.vif,
+                        'status' : NETIF_INTERFACE_STATUS_CONNECTED,
+                        'evtchn' : dev.evtchn['port2'],
+                        'mac'    : dev.mac })
+        self.writeRequest(msg)
+
+    def send_be_create(self, vif):
+        dev = self.devices[vif]
+        msg = packMsg('netif_be_create_t',
+                      { 'domid'        : self.dom,
+                        'netif_handle' : dev.vif,
+                        'mac'          : dev.mac })
+        self.factory.writeRequest(msg)
+
+    def send_be_disconnect(self, vif):
+        dev = self.devices[vif]
+        msg = packMsg('netif_be_disconnect_t',
+                      { 'domid'        : self.dom,
+                        'netif_handle' : dev.vif })
+        self.factory.writeRequest(msg)
+
+    def send_be_destroy(self, vif):
+        print 'NetifController>send_be_destroy>', 'dom=', self.dom, 'vif=', vif
+        PrettyPrint.prettyprint(self.sxpr())
+        dev = self.devices[vif]
+        del self.devices[vif]
+        msg = packMsg('netif_be_destroy_t',
+                      { 'domid'        : self.dom,
+                        'netif_handle' : vif })
+        self.factory.writeRequest(msg)
diff --git a/tools/xen/lib/xend/server/params.py b/tools/xen/lib/xend/server/params.py
new file mode 100644 (file)
index 0000000..7949f14
--- /dev/null
@@ -0,0 +1,10 @@
+# The following parameters could be placed in a configuration file.
+PID_FILE  = '/var/run/xend.pid'
+LOG_FILE  = '/var/log/xend.log'
+USER = 'root'
+CONTROL_DIR  = '/var/run/xend'
+MGMT_SOCK    = 'xendsock' # relative to CONTROL_DIR
+EVENT_PORT = 8001
+
+CONSOLE_PORT_BASE = 9600
+
diff --git a/tools/xen/lib/xend/sxp.py b/tools/xen/lib/xend/sxp.py
new file mode 100644 (file)
index 0000000..dd4fece
--- /dev/null
@@ -0,0 +1,557 @@
+#!/usr/bin/python2
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""
+Input-driven parsing for s-expression (sxp) format.
+Create a parser: pin = Parser();
+Then call pin.input(buf) with your input.
+Call pin.input_eof() when done.
+Use pin.read() to see if a value has been parsed, pin.get_val()
+to get a parsed value. You can call ready and get_val at any time -
+you don't have to wait until after calling input_eof.
+
+"""
+from __future__ import generators
+
+import sys
+import types
+import errno
+import string
+
+__all__ = [
+    "mime_type", 
+    "ParseError", 
+    "Parser", 
+    "atomp", 
+    "show", 
+    "show_xml", 
+    "elementp", 
+    "name", 
+    "attributes", 
+    "attribute", 
+    "children", 
+    "child", 
+    "child_at", 
+    "child0", 
+    "child1", 
+    "child2", 
+    "child3", 
+    "child4", 
+    "child_value", 
+    "has_id", 
+    "with_id", 
+    "child_with_id", 
+    "elements", 
+    "parse", 
+    ]
+
+mime_type = "application/sxp"
+
+escapes = {
+    'a': '\a',
+    'b': '\b',
+    't': '\t',
+    'n': '\n',
+    'v': '\v',
+    'f': '\f',
+    'r': '\r',
+    '\\': '\\',
+    '\'': '\'',
+    '\"': '\"'}
+
+k_list_open  = "("
+k_list_close = ")"
+k_attr_open  = "@"
+k_eval       = "!"
+
+escapes_rev = {}
+for k in escapes:
+    escapes_rev[escapes[k]] = k
+
+class ParseError(StandardError):
+
+    def __init__(self, parser, value):
+        self.parser = parser
+        self.value = value
+
+    def __str__(self):
+        return self.value
+
+class ParserState:
+
+    def __init__(self, fn, parent=None):
+        self.parent = parent
+        self.buf = ''
+        self.val = []
+        self.delim = None
+        self.fn = fn
+
+    def push(self, fn):
+        return ParserState(fn, parent=self)
+    
+class Parser:
+
+    def __init__(self):
+        self.error = sys.stderr
+        self.reset()
+
+    def reset(self):
+        self.val = []
+        self.eof = 0
+        self.err = 0
+        self.line_no = 0
+        self.char_no = 0
+        self.state = None
+
+    def push_state(self, fn):
+        self.state = self.state.push(fn)
+
+    def pop_state(self):
+        val = self.state
+        self.state = self.state.parent
+        if self.state and self.state.fn == self.state_start:
+            # Return to start state - produce the value.
+            self.val += self.state.val
+            self.state.val = []
+        return val
+
+    def in_class(self, c, s):
+        return s.find(c) >= 0
+        
+    def in_space_class(self, c):
+        return self.in_class(c, ' \t\n\v\f\r')
+
+    def is_separator(self, c):
+        return self.in_class(c, '{}()<>[]!;')
+
+    def in_comment_class(self, c):
+        return self.in_class(c, '#')
+
+    def in_string_quote_class(self, c):
+        return self.in_class(c, '"\'')
+
+    def in_printable_class(self, c):
+        return self.in_class(c, string.printable)
+
+    def set_error_stream(self, error):
+        self.error = error
+
+    def has_error(self):
+        return self.err > 0
+
+    def at_eof(self):
+        return self.eof
+
+    def input_eof(self):
+        self.eof = 1
+        self.input_char(-1)
+
+    def input(self, buf):
+        if not buf or len(buf) == 0:
+            self.input_eof()
+        else:
+            for c in buf:
+                self.input_char(c)
+
+    def input_char(self, c):
+        if self.at_eof():
+            pass
+        elif c == '\n':
+            self.line_no += 1
+            self.char_no = 0
+        else:
+           self.char_no += 1 
+
+        if self.state is None:
+            self.begin_start(None)
+        self.state.fn(c)
+
+    def ready(self):
+        return len(self.val) > 0
+
+    def get_val(self):
+        v = self.val[0]
+        self.val = self.val[1:]
+        return v
+
+    def get_all(self):
+        return self.val
+
+    def begin_start(self, c):
+        self.state = ParserState(self.state_start)
+
+    def end_start(self):
+        self.val += self.state.val
+        self.pop_state()
+    
+    def state_start(self, c):
+        if self.at_eof():
+            self.end_start()
+        elif self.in_space_class(c):
+            pass
+        elif self.in_comment_class(c):
+            self.begin_comment(c)
+        elif c == k_list_open:
+            self.begin_list(c)
+        elif c == k_list_close:
+            raise ParseError(self, "syntax error: "+c)
+        elif self.in_string_quote_class(c):
+            self.begin_string(c)
+        elif self.in_printable_class(c):
+            self.begin_atom(c)
+        elif c == chr(4):
+            # ctrl-D, EOT: end-of-text.
+            self.input_eof()
+        else:
+            raise ParseError(self, "invalid character: code %d" % ord(c))
+
+    def begin_comment(self, c):
+        self.push_state(self.state_comment)
+        self.state.buf += c
+
+    def end_comment(self):
+        self.pop_state()
+    
+    def state_comment(self, c):
+        if c == '\n' or self.at_eof():
+            self.end_comment()
+        else:
+            self.state.buf += c
+
+    def begin_string(self, c):
+        self.push_state(self.state_string)
+        self.state.delim = c
+
+    def end_string(self):
+        val = self.state.buf
+        self.state.parent.val.append(val)
+        self.pop_state()
+        
+    def state_string(self, c):
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        elif c == self.state.delim:
+            self.end_string()
+        elif c == '\\':
+            self.push_state(self.state_escape)
+        else:
+            self.state.buf += c
+
+    def state_escape(self, c):
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        d = escapes.get(c)
+        if d:
+            self.state.parent.buf += d
+            self.pop_state()
+        elif c == 'x':
+            self.state.fn = self.state_hex
+            self.state.val = 0
+        else:
+            self.state.fn = self.state_octal
+            self.state.val = 0
+            self.input_char(c)
+
+    def state_octal(self, c):
+        def octaldigit(c):
+            self.state.val *= 8
+            self.state.val += ord(c) - ord('0')
+            self.state.buf += c
+            if self.state.val < 0 or self.state.val > 0xff:
+                raise ParseError(self, "invalid octal escape: out of range " + self.state.buf)
+            if len(self.state.buf) == 3:
+               octaldone()
+               
+        def octaldone():
+            d = chr(self.state.val)
+            self.state.parent.buf += d
+            self.pop_state()
+            
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        elif '0' <= c <= '7':
+            octaldigit(c)
+        elif len(self.buf):
+            octaldone()
+            self.input_char(c)
+
+    def state_hex(self, c):
+        def hexdone():
+            d = chr(self.state.val)
+            self.state.parent.buf += d
+            self.pop_state()
+            
+        def hexdigit(c, d):
+            self.state.val *= 16
+            self.state.val += ord(c) - ord(d)
+            self.state.buf += c
+            if self.state.val < 0 or self.state.val > 0xff:
+                raise ParseError(self, "invalid hex escape: out of range " + self.state.buf)
+            if len(self.state.buf) == 2:
+                hexdone()
+            
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        elif '0' <= c <= '9':
+            hexdigit(c, '0')
+        elif 'A' <= c <= 'F':
+            hexdigit(c, 'A')
+        elif 'a' <= c <= 'f':
+            hexdigit(c, 'a')
+        elif len(buf):
+            hexdone()
+            self.input_char(c)
+
+    def begin_atom(self, c):
+        self.push_state(self.state_atom)
+        self.state.buf = c
+
+    def end_atom(self):
+        val = self.state.buf
+        self.state.parent.val.append(val)
+        self.pop_state()
+    
+    def state_atom(self, c):
+        if self.at_eof():
+            self.end_atom()
+        elif (self.is_separator(c) or
+              self.in_space_class(c) or
+              self.in_comment_class(c)):
+            self.end_atom()
+            self.input_char(c)
+        else:
+            self.state.buf += c
+
+    def begin_list(self, c):
+        self.push_state(self.state_list)
+
+    def end_list(self):
+        val = self.state.val
+        self.state.parent.val.append(val)
+        self.pop_state()
+
+    def state_list(self, c):
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        elif c == k_list_close:
+            self.end_list()
+        else:
+            self.state_start(c)
+
+def atomp(sxpr):
+    if sxpr.isalnum() or sxpr == '@':
+        return 1
+    for c in sxpr:
+        if c in string.whitespace: return 0
+        if c in '"\'\\(){}[]<>$#&%^': return 0
+        if c in string.ascii_letters: continue
+        if c in string.digits: continue
+        if c in '.-_:/~': continue
+        return 0
+    return 1
+    
+def show(sxpr, out=sys.stdout):
+    if isinstance(sxpr, types.ListType):
+        out.write(k_list_open)
+        i = 0
+        for x in sxpr:
+            if i: out.write(' ')
+            show(x, out)
+            i += 1
+        out.write(k_list_close)
+    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
+        out.write(sxpr)
+    else:
+        #out.write("'" + str(sxpr) + "'")
+        out.write(repr(str(sxpr)))
+
+def show_xml(sxpr, out=sys.stdout):
+    if isinstance(sxpr, types.ListType):
+        element = name(sxpr)
+        out.write('<%s' % element)
+        for attr in attributes(sxpr):
+            out.write(' %s=%s' % (attr[0], attr[1]))
+        out.write('>')
+        i = 0
+        for x in children(sxpr):
+            if i: out.write(' ')
+            show_xml(x, out)
+            i += 1
+        out.write('</%s>' % element)
+    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
+        out.write(sxpr)
+    else:
+        out.write(str(sxpr))
+
+def elementp(sxpr, elt=None):
+    return (isinstance(sxpr, types.ListType)
+            and len(sxpr)
+            and (None == elt or sxpr[0] == elt))
+
+def name(sxpr):
+    val = None
+    if isinstance(sxpr, types.StringType):
+        val = sxpr
+    elif isinstance(sxpr, types.ListType) and len(sxpr):
+        val = sxpr[0]
+    return val
+
+def attributes(sxpr):
+    val = []
+    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
+        attr = sxpr[1]
+        if elementp(attr, k_attr_open):
+            val = attr[1:]
+    return val
+
+def attribute(sxpr, key, val=None):
+    for x in attributes(sxpr):
+        if x[0] == key:
+            val = x[1]
+            break
+    return val
+
+def children(sxpr, elt=None):
+    val = []
+    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
+        i = 1
+        x = sxpr[i]
+        if elementp(x, k_attr_open):
+            i += 1
+        val = sxpr[i : ]
+    if elt:
+        def iselt(x):
+            return elementp(x, elt)
+        val = filter(iselt, val)
+    return val
+
+def child(sxpr, elt, val=None):
+    for x in children(sxpr):
+        if elementp(x, elt):
+            val = x
+            break
+    return val
+
+def child_at(sxpr, index, val=None):
+    kids = children(sxpr)
+    if len(kids) > index:
+        val = kids[index]
+    return val
+
+def child0(sxpr, val=None):
+    return child_at(sxpr, 0, val)
+
+def child1(sxpr, val=None):
+    return child_at(sxpr, 1, val)
+
+def child2(sxpr, val=None):
+    return child_at(sxpr, 2, val)
+
+def child3(sxpr, val=None):
+    return child_at(sxpr, 3, val)
+
+def child4(sxpr, val=None):
+    return child_at(sxpr, 4, val)
+
+def child_value(sxpr, elt, val=None):
+    kid = child(sxpr, elt)
+    if kid:
+        val = child_at(kid, 0, val)
+    return val
+
+def has_id(sxpr, id):
+    """Test if an s-expression has a given id.
+    """
+    return attribute(sxpr, 'id') == id
+
+def with_id(sxpr, id, val=None):
+    """Find the first s-expression with a given id, at any depth.
+
+    sxpr   s-exp or list
+    id     id
+    val    value if not found (default None)
+
+    return s-exp or val
+    """
+    if isinstance(sxpr, types.ListType):
+        for n in sxpr:
+            if has_id(n, id):
+                val = n
+                break
+            v = with_id(n, id)
+            if v is None: continue
+            val = v
+            break
+    return val
+
+def child_with_id(sxpr, id, val=None):
+    """Find the first child with a given id.
+
+    sxpr   s-exp or list
+    id     id
+    val    value if not found (default None)
+
+    return s-exp or val
+    """
+    if isinstance(sxpr, types.ListType):
+        for n in sxpr:
+            if has_id(n, id):
+                val = n
+                break
+    return val
+
+def elements(sxpr, ctxt=None):
+    """Generate elements (at any depth).
+    Visit elements in pre-order.
+    Values generated are (node, context)
+    The context is None if there is no parent, otherwise
+    (index, parent, context) where index is the node's index w.r.t its parent,
+    and context is the parent's context.
+
+    sxpr   s-exp
+
+    returns generator
+    """
+    yield (sxpr, ctxt)
+    i = 0
+    for n in children(sxpr):
+        if isinstance(n, types.ListType):
+            # Calling elements() recursively does not generate recursively,
+            # it just returns a generator object. So we must iterate over it.
+            for v in elements(n, (i, sxpr, ctxt)):
+                yield v
+        i += 1
+
+def parse(io):
+    """Completely parse all input from 'io'.
+
+    io input file object
+    returns list of values, None if incomplete
+    raises ParseError on parse error
+    """
+    pin = Parser()
+    while 1:
+        buf = io.readline()
+        pin.input(buf)
+        if len(buf) == 0:
+            break
+    if pin.ready():
+        val = pin.get_all()
+    else:
+        val = None
+    return val
+   
+
+if __name__ == '__main__':
+    print ">main"
+    pin = Parser()
+    while 1:
+        buf = sys.stdin.read(1024)
+        #buf = sys.stdin.readline()
+        pin.input(buf)
+        while pin.ready():
+            val = pin.get_val()
+            print
+            print '****** val=', val
+        if len(buf) == 0:
+            break
+
diff --git a/tools/xen/lib/xm/__init__.py b/tools/xen/lib/xm/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/xen/lib/xm/create.py b/tools/xen/lib/xm/create.py
new file mode 100644 (file)
index 0000000..1def190
--- /dev/null
@@ -0,0 +1,366 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Domain creation.
+"""
+import string
+import sys
+
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+from xen.xend.XendClient import server
+
+from xen.xend.xm.opts import *
+
+gopts = Opts(use="""[options]
+
+Create a domain.
+""")
+
+gopts.opt('help', short='h',
+         fn=set_true, default=0,
+         use="Print this help.")
+
+gopts.opt('quiet', short='q',
+         fn=set_true, default=0,
+         use="Quiet.")
+
+gopts.opt('path', val='PATH',
+         fn=set_value, default='.:/etc/xen',
+         use="Search path for default scripts.")
+
+gopts.opt('defaults', short='f', val='FILE',
+         fn=set_value, default='xmdefaults',
+         use="Use the given default script.")
+
+gopts.opt('config', short='F', val='FILE',
+         fn=set_value, default=None,
+         use='Domain configuration to use (SXP).')
+
+gopts.opt('load', short='L', val='FILE',
+          fn=set_value, default=None,
+          use='Domain saved state to load.')
+
+gopts.opt('define', short='D', val='VAR=VAL',
+         fn=set_var, default=None,
+         use="""Set a variable before loading defaults, e.g. '-D vmid=3'
+         to set vmid. May be repeated to set more thanone variable.""")
+
+gopts.opt('dryrun', short='n',
+         fn=set_true, default=0,
+         use="Dry run - print the config but don't create the domain.")
+
+gopts.opt('name', short='N', val='NAME',
+          fn=set_value, default=None,
+          use="Domain name.")
+
+gopts.opt('console', short='c',
+         fn=set_true, default=0,
+         use="Connect to console after domain is created.")
+
+gopts.opt('kernel', short='k', val='FILE',
+         fn=set_value, default=None,
+         use="Path to kernel image.")
+
+gopts.opt('ramdisk', short='r', val='FILE',
+         fn=set_value, default='',
+         use="Path to ramdisk.")
+
+gopts.opt('builder', short='b', val='FUNCTION',
+         fn=set_value, default='linux',
+         use="Function to use to build the domain.")
+
+gopts.opt('memory', short='m', val='MEMORY',
+         fn=set_value, default=128,
+         use="Domain memory in MB.")
+
+gopts.opt('blkif',
+          fn=set_true, default=0,
+          use="Make the domain a block device backend.")
+
+gopts.opt('netif',
+          fn=set_true, default=0,
+          use="Make the domain a network interface backend.")
+
+gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE',
+         fn=append_value, default=[],
+         use="""Add a disk device to a domain. The physical device is DEV, which
+         is exported to the domain as VDEV. The disk is read-only if MODE
+         is 'r', read-write if MODE is 'w'.
+         The option may be repeated to add more than one disk.
+         """)
+
+gopts.opt('pci', val='BUS,DEV,FUNC',
+         fn=append_value, default=[],
+         use="""Add a PCI device to a domain, using given params (in hex).
+         For example '-pci c0,02,1a'.
+         The option may be repeated to add more than one pci device.
+         """)
+
+gopts.opt('ipaddr', short='i', val="IPADDR",
+         fn=append_value, default=[],
+         use="Add an IP address to the domain.")
+
+gopts.opt('vif', val="mac=MAC,bridge=BRIDGE",
+         fn=append_value, default=[],
+         use="""Add a network interface with the given MAC address and bridge.
+         If mac is not specified a random MAC address is used.
+         If bridge is not specified the default bridge is used.
+         This option may be repeated to add more than one vif.
+         Specifying vifs will increase the number of interfaces as needed.
+         """)
+
+gopts.opt('nics', val="NUM",
+         fn=set_int, default=1,
+         use="""Set the number of network interfaces.
+         Use the vif option to define interface parameters, otherwise
+         defaults are used. Specifying vifs will increase the
+         number of interfaces as needed.
+         """)
+
+gopts.opt('root', short='R', val='DEVICE',
+         fn=set_value, default='',
+         use="""Set the root= parameter on the kernel command line.
+         Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
+
+gopts.opt('extra', short='E', val="ARGS",
+         fn=set_value, default='',
+         use="Set extra arguments to append to the kernel command line.")
+
+gopts.opt('ip', short='I', val='IPADDR',
+         fn=set_value, default='',
+         use="Set the kernel IP interface address.")
+
+gopts.opt('gateway', val="IPADDR",
+         fn=set_value, default='',
+         use="Set the kernel IP gateway.")
+
+gopts.opt('netmask', val="MASK",
+         fn=set_value, default = '',
+         use="Set the kernel IP netmask.")
+
+gopts.opt('hostname', val="NAME",
+         fn=set_value, default='',
+         use="Set the kernel IP hostname.")
+
+gopts.opt('interface', val="INTF",
+         fn=set_value, default="eth0",
+         use="Set the kernel IP interface name.")
+
+gopts.opt('dhcp', val="off|dhcp",
+         fn=set_value, default='off',
+         use="Set the kernel dhcp option.")
+
+gopts.opt('nfs_server', val="IPADDR",
+         fn=set_value, default=None,
+         use="Set the address of the NFS server for NFS root.")
+
+gopts.opt('nfs_root', val="PATH",
+         fn=set_value, default=None,
+         use="Set the path of the root NFS directory.")
+
+def strip(pre, s):
+    """Strip prefix 'pre' if present.
+    """
+    if s.startswith(pre):
+        return s[len(pre):]
+    else:
+        return s
+
+def configure_image(config, opts):
+    """Create the image config.
+    """
+    config_image = [ opts.builder ]
+    config_image.append([ 'kernel', os.path.abspath(opts.kernel) ])
+    if opts.ramdisk:
+        config_image.append([ 'ramdisk', os.path.abspath(opts.ramdisk) ])
+    if opts.cmdline_ip:
+        cmdline_ip = strip('ip=', opts.cmdline_ip)
+        config_image.append(['ip', cmdline_ip])
+    if opts.root:
+        cmdline_root = strip('root=', opts.root)
+        config_image.append(['root', cmdline_root])
+    if opts.extra:
+        config_image.append(['args', opts.extra])
+    config.append(['image', config_image ])
+    
+def configure_disks(config_devs, opts):
+    """Create the config for disks (virtual block devices).
+    """
+    for (uname, dev, mode) in opts.disk:
+        config_vbd = ['vbd',
+                      ['uname', uname],
+                      ['dev', dev ],
+                      ['mode', mode ] ]
+        config_devs.append(['device', config_vbd])
+
+def configure_pci(config_devs, opts):
+    """Create the config for pci devices.
+    """
+    for (bus, dev, func) in opts.pci:
+        config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
+        config_devs.append(['device', config_pci])
+
+def configure_vifs(config_devs, opts):
+    """Create the config for virtual network interfaces.
+    """
+    vifs = opts.vif
+    vifs_n = max(opts.nics, len(vifs))
+
+    for idx in range(0, vifs_n):
+        if idx < len(vifs):
+            d = vifs[idx]
+            mac = d.get('mac')
+            bridge = d.get('bridge')
+        else:
+            mac = None
+            bridge = None
+        config_vif = ['vif']
+        if mac:
+            config_vif.append(['mac', mac])
+        if bridge:
+            config_vif.append(['bridge', bridge])
+        config_devs.append(['device', config_vif])
+
+def configure_vfr(config, opts):
+     if not opts.ipaddr: return
+     config_vfr = ['vfr']
+     idx = 0 # No way of saying which IP is for which vif?
+     for ip in opts.ipaddr:
+         config_vfr.append(['vif', ['id', idx], ['ip', ip]])
+     config.append(config_vfr)
+
+
+def make_config(opts):
+    """Create the domain configuration.
+    """
+    
+    config = ['vm',
+              ['name', opts.name ],
+              ['memory', opts.memory ] ]
+    if opts.cpu:
+        config.append(['cpu', opts.cpu])
+    if opts.blkif:
+        config.append(['backend', ['blkif']])
+    if opts.netif:
+        config.append(['backend', ['netif']])
+    
+    configure_image(config, opts)
+    config_devs = []
+    configure_disks(config_devs, opts)
+    configure_pci(config_devs, opts)
+    configure_vifs(config_devs, opts)
+    config += config_devs
+    return config
+
+def preprocess_disk(opts):
+    if not opts.disk: return
+    disk = []
+    for v in opts.disk:
+        d = v.split(',')
+        if len(d) != 3:
+            opts.err('Invalid disk specifier: ' + v)
+        disk.append(d)
+    opts.disk = disk
+
+def preprocess_pci(opts):
+    if not opts.pci: return
+    pci = []
+    for v in opts.pci:
+        d = v.split(',')
+        if len(d) != 3:
+            opts.err('Invalid pci specifier: ' + v)
+        # Components are in hex: add hex specifier.
+        hexd = map(lambda v: '0x'+v, d)
+        pci.append(hexd)
+    opts.pci = pci
+
+def preprocess_vifs(opts):
+    if not opts.vif: return
+    vifs = []
+    for vif in opts.vif:
+        d = {}
+        a = vif.split(',')
+        for b in a:
+            (k, v) = b.strip().split('=')
+            k = k.strip()
+            v = v.strip()
+            if k not in ['mac', 'bridge']:
+                opts.err('Invalid vif specifier: ' + vif)
+            d[k] = v
+        vifs.append(d)
+    opts.vif = vifs
+
+def preprocess_ip(opts):
+    setip = (opts.hostname or opts.netmask
+             or opts.gateway or opts.dhcp or opts.interface)
+    if not setip: return
+    #if not opts
+    ip = (opts.ip
+          + ':'
+          + ':' + opts.gateway
+          + ':' + opts.netmask
+          + ':' + opts.hostname
+          + ':' + opts.interface
+          + ':' + opts.dhcp)
+    opts.cmdline_ip = ip
+
+def preprocess_nfs(opts):
+    if (opts.nfs_root or opts.nfs_server):
+        if (not opts.nfs_root) or (not opts.nfs_server):
+            opts.err('Must set nfs root and nfs server')
+    else:
+        return
+    nfs = 'nfsroot=' + opts.nfs_server + ':' + opts.nfs_root
+    opts.extra = nfs + ' ' + opts.extra
+    
+def preprocess(opts):
+    if not opts.kernel:
+        opts.err("No kernel specified")
+    preprocess_disk(opts)
+    preprocess_pci(opts)
+    preprocess_vifs(opts)
+    preprocess_ip(opts)
+    preprocess_nfs(opts)
+         
+def make_domain(opts, config):
+    """Create, build and start a domain.
+    Returns: [int] the ID of the new domain.
+    """
+    if opts.vals.load:
+        filename = os.path.abspath(opts.vals.load)
+        dominfo = server.xend_domain_restore(filename, config)
+    else:
+        dominfo = server.xend_domain_create(config)
+
+    dom = int(sxp.child_value(dominfo, 'id'))
+    console_info = sxp.child(dominfo, 'console')
+    if console_info:
+        console_port = int(sxp.child_value(console_info, 'port'))
+    else:
+        console_port = None
+    
+    if server.xend_domain_unpause(dom) < 0:
+        server.xend_domain_destroy(dom)
+        opts.err("Failed to start domain %d" % dom)
+    opts.info("Started domain %d, console on port %d"
+              % (dom, console_port))
+    return (dom, console_port)
+
+def main(argv):
+    opts = gopts
+    args = opts.parse(argv)
+    if opts.vals.help:
+        opts.usage()
+        return
+    if opts.vals.config:
+        pass
+    else:
+        opts.load_defaults()
+    preprocess(opts.vals)
+    config = make_config(opts.vals)
+    if opts.vals.dryrun:
+        PrettyPrint.prettyprint(config)
+    else:
+        make_domain(opts, config)
+        
+if __name__ == '__main__':
+    main(sys.argv)
diff --git a/tools/xen/lib/xm/main.py b/tools/xen/lib/xm/main.py
new file mode 100644 (file)
index 0000000..d03ceae
--- /dev/null
@@ -0,0 +1,448 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Grand unified management application for Xen.
+"""
+import os
+import os.path
+import sys
+from getopt import getopt
+
+from xen.xend import PrettyPrint
+from xen.xend import sxp
+from xen.xend.XendClient import server
+from xen.xend.xm import create, shutdown
+
+class Prog:
+    """Base class for sub-programs.
+    """
+
+    """Program group it belongs to"""
+    group = 'all'
+    """Program name."""
+    name = '??'
+    """Short program info."""
+    info = ''
+
+    def __init__(self, xm):
+        self.xm = xm
+
+    def err(self, msg):
+        self.xm.err(msg)
+
+    def help(self, args):
+        self.shortHelp(args)
+
+    def shortHelp(self, args):
+        print "%-14s %s" % (self.name, self.info)
+
+    def main(self, args):
+        """Program main entry point.
+        """
+        pass
+
+
+class ProgUnknown(Prog):
+
+    name = 'unknown'
+    info = ''
+    
+    def help(self, args):
+        self.xm.err("Unknown command: %s\nTry '%s help' for more information."
+                    % (args[0], self.xm.name))
+
+    main = help
+
+class Xm:
+    """Main application.
+    """
+
+    def __init__(self):
+        self.name = 'xm'
+        self.unknown = ProgUnknown(self)
+        self.progs = {}
+
+    def err(self, msg):
+        print >>sys.stderr, "Error:", msg
+        sys.exit(1)
+
+    def main(self, args):
+        """Main entry point. Dispatches to the progs.
+        """
+        self.name = args[0]
+        if len(args) < 2:
+            self.err("Missing command\nTry '%s help' for more information."
+                     % self.name)
+        help = self.helparg(args)
+        p = self.getprog(args[1], self.unknown)
+        if help:
+            p.help(args[1:])
+        else:
+            p.main(args[1:])
+
+    def helparg(self, args):
+        for a in args:
+            if a in ['-h', '--help']:
+                return 1
+        return 0
+
+    def prog(self, pklass):
+        """Add a sub-program.
+
+        pklass  program class (Prog subclass)
+        """
+        p = pklass(self)
+        self.progs[p.name] = p
+        return p
+
+    def getprog(self, name, val=None):
+        """Get a sub-program.
+        """
+        return self.progs.get(name, val)
+
+    def proglist(self):
+        """Get a list of sub-programs, ordered by group.
+        """
+        groups = {}
+        for p in self.progs.values():
+            l = groups.get(p.group, [])
+            l.append(p)
+            groups[p.group] = l
+        kl = groups.keys()
+        kl.sort()
+        pl = []
+        for k in kl:
+            l = groups[k]
+            l.sort()
+            pl += l
+        return pl
+        
+# Create the application object, then add the sub-program classes.
+xm = Xm()
+
+class ProgHelp(Prog):
+
+    name = "help"
+    info = "Print help."
+    
+    def help(self, args):
+        if len(args) == 2:
+            name = args[1]
+            p = self.xm.getprog(name)
+            if p:
+                p.help(args[1:])
+            else:
+                print '%s: Unknown command: %s' % (self.name, name)
+        else:
+            for p in self.xm.proglist():
+                p.shortHelp(args)
+            print "\nTry '%s help CMD' for help on CMD" % self.xm.name
+
+    main = help
+
+xm.prog(ProgHelp)
+
+class ProgCreate(Prog):
+
+    group = 'domain'
+    name = "create"
+    info = """Create a domain."""
+
+    def help(self, args):
+        create.main([args[0], '-h'])
+
+    def main(self, args):
+        create.main(args)
+
+xm.prog(ProgCreate)
+
+class ProgSave(Prog):
+    group = 'domain'
+    name = "save"
+    info = """Save domain state (and config) to file."""
+
+    def help(self, args):
+        print args[0], "DOM FILE"
+        print """\nSave domain with id DOM to FILE."""
+        
+    def main(self, args):
+        if len(args) < 3: self.err("%s: Missing arguments" % args[0])
+        dom = args[1]
+        savefile = os.path.abspath(args[2])
+        server.xend_domain_save(dom, savefile)
+
+xm.prog(ProgSave)
+
+class ProgRestore(Prog):
+    group = 'domain'
+    name = "restore"
+    info = """Create a domain from a saved state."""
+
+    def help(self, args):
+        print args[0], "FILE [CONFIG]"
+        print "\nRestore a domain from FILE using configuration CONFIG."
+    
+    def main(self, help, args):
+        if len(args) < 2: self.err("%s: Missing arguments" % args[0])
+        savefile =  os.path.abspath(args[1])
+        if len(args) >= 3:
+            configfile = os.path.abspath(args[2])
+        else:
+            configfile = None
+        info = server.xend_domain_restore(savefile, configfile)
+        PrettyPrint.prettyprint(info)
+
+xm.prog(ProgRestore)
+
+class ProgList(Prog):
+    group = 'domain'
+    name = "list"
+    info = """List info about domains."""
+
+    short_options = 'l'
+    long_options = ['long']
+
+    def help(self, args):
+        if help:
+            print args[0], '[options] [DOM...]'
+            print """\nGet information about domains.
+            Either all domains or the domains given.
+
+            -l, --long   Get more detailed information.
+            """
+            return
+        
+    def main(self, args):
+        use_long = 0
+        (options, params) = getopt(args[1:],
+                                   self.short_options,
+                                   self.long_options)
+        n = len(params)
+        for (k, v) in options:
+            if k in ['-l', '--long']:
+                use_long = 1
+                
+        if n == 0:
+            doms = map(int, server.xend_domains())
+            doms.sort()
+        else:
+            doms = map(int, params)
+            
+        if use_long:
+            self.long_list(doms)
+        else:
+            self.brief_list(doms)
+
+    def brief_list(self, doms):
+        print 'Dom  Name             Mem(MB)  CPU  State  Time(s)'
+        for dom in doms:
+            info = server.xend_domain(dom)
+            d = {}
+            d['dom'] = int(dom)
+            d['name'] = sxp.child_value(info, 'name', '??')
+            d['mem'] = int(sxp.child_value(info, 'memory', '0'))
+            d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
+            d['state'] = sxp.child_value(info, 'state', '??')
+            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
+            print ("%(dom)-4d %(name)-16s %(mem)7d  %(cpu)3d  %(state)5s  %(cpu_time)7.1f" % d)
+
+    def long_list(self, doms):
+        for dom in doms:
+            info = server.xend_domain(dom)
+            print '\nDomain %d' % dom
+            PrettyPrint.prettyprint(info)
+
+xm.prog(ProgList)
+
+class ProgDestroy(Prog):
+    group = 'domain'
+    name = "destroy"
+    info = """Terminate a domain immediately."""
+
+    def help(self, args):
+        print args[0], 'DOM'
+        print '\nTerminate domain DOM immediately.'
+
+    def main(self, args):
+        if len(args) < 2: self.err("%s: Missing domain" % args[0])
+        dom = args[1]
+        server.xend_domain_destroy(dom)
+
+xm.prog(ProgDestroy)
+
+class ProgShutdown(Prog):
+    group = 'domain'
+    name = "shutdown"
+    info = """Shutdown a domain."""
+
+    def help(self, args):
+        shutdown.main([args[0], '-h'])
+    
+    def main(self, args):
+        shutdown.main(args)
+
+xm.prog(ProgShutdown)
+
+class ProgPause(Prog):
+    group = 'domain'
+    name = "pause"
+    info = """Pause execution of a domain."""
+
+    def help(self, args):
+        print args[0], 'DOM'
+        print '\nPause execution of domain DOM.'
+
+    def main(self, args):
+        if len(args) < 2: self.err("%s: Missing domain" % args[0])
+        dom = args[1]
+        server.xend_domain_pause(dom)
+
+xm.prog(ProgPause)
+
+class ProgUnpause(Prog):
+    group = 'domain'
+    name = "unpause"
+    info = """Unpause a paused domain."""
+
+    def help(self, args):
+        print args[0], 'DOM'
+        print '\nUnpause execution of domain DOM.'
+
+    def main(self, args):
+        if len(args) < 2: self.err("%s: Missing domain" % args[0])
+        dom = args[1]
+        server.xend_domain_unpause(dom)
+
+xm.prog(ProgUnpause)
+
+class ProgPincpu(Prog):
+    group = 'domain'
+    name = "pincpu"
+    info = """Pin a domain to a cpu. """
+
+    def help(self, args):
+        print args[0],'DOM CPU'
+        print '\nPin domain DOM to cpu CPU.'
+
+    def main(self, args):
+        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
+        v = map(int, args[1:3])
+        server.xend_domain_pincpu(*v)
+
+xm.prog(ProgPincpu)
+
+class ProgBvt(Prog):
+    group = 'scheduler'
+    name = "bvt"
+    info = """Set BVT scheduler parameters."""
+    
+    def help(self, args):
+        print args[0], "DOM MCUADV WARP WARPL WARPU"
+        print '\nSet Borrowed Virtual Time scheduler parameters.'
+
+    def main(self, args):
+        if len(args) != 6: self.err("%s: Invalid argument(s)" % args[0])
+        v = map(int, args[1:6])
+        server.xend_domain_cpu_bvt_set(*v)
+
+xm.prog(ProgBvt)
+
+class ProgBvtslice(Prog):
+    group = 'scheduler'
+    name = "bvtslice"
+    info = """Set the BVT scheduler slice."""
+
+    def help(self, args):
+        print args[0], 'SLICE'
+        print '\nSet Borrowed Virtual Time scheduler slice.'
+
+    def main(self, args):
+        if len(args) < 2: self.err('%s: Missing slice' % args[0])
+        server.xend_node_cpu_bvt_slice_set(slice)
+
+xm.prog(ProgBvtslice)
+
+class ProgAtropos(Prog):
+    group = 'scheduler'
+    name= "atropos"
+    info = """Set atropos parameters."""
+
+    def help(self, args):
+        print args[0], "DOM PERIOD SLICE LATENCY XTRATIME"
+        print "\nSet atropos parameters."
+
+    def main(self, args):
+        if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
+        v = map(int, args[1:5])
+        server.xend_domain_cpu_atropos_set(*v)
+
+xm.prog(ProgAtropos)
+
+class ProgRrobin(Prog):
+    group = 'scheduler'
+    name = "rrobin"
+    info = """Set round robin slice."""
+
+    def help(self, args):
+        print args[0], "SLICE"
+        print "\nSet round robin scheduler slice."
+
+    def main(self, args):
+        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
+        rrslice = int(args[1])
+        server.xend_node_rrobin_set(rrslice)
+
+xm.prog(ProgRrobin)
+
+class ProgInfo(Prog):
+    group = 'host'
+    name = "info"
+    info = """Get information about the xen host."""
+
+    def main(self, args):
+        info = server.xend_node()
+        for x in info[1:]:
+            print "%-23s:" % x[0], x[1]
+
+xm.prog(ProgInfo)
+
+class ProgConsoles(Prog):
+    group = 'console'
+    name = "consoles"
+    info = """Get information about domain consoles."""
+
+    def main(self, args):
+        l = server.xend_consoles()
+        print "Dom Port  Id"
+        for x in l:
+            info = server.xend_console(x)
+            d = {}
+            d['dom'] = sxp.child(info, 'dst', ['dst', '?', '?'])[1]
+            d['port'] = sxp.child_value(info, 'port', '?')
+            d['id'] = sxp.child_value(info, 'id', '?')
+            print "%(dom)3s %(port)4s %(id)3s" % d
+
+xm.prog(ProgConsoles)
+
+class ProgConsole(Prog):
+    group = 'console'
+    name = "console"
+    info = """Open a console to a domain."""
+    
+    def help(self, args):
+        print "console DOM"
+        print "\nOpen a console to domain DOM."
+
+    def main(self, args):
+        if len(args) < 2: self.err("%s: Missing domain" % args[0])
+        dom = args[1]
+        info = server.xend_domain(dom)
+        console = sxp.child(info, "console")
+        if not console:
+            self.err("No console information")
+        port = sxp.child_value(console, "port")
+        from xenctl import console_client
+        console_client.connect("localhost", int(port))
+
+xm.prog(ProgConsole)
+
+def main(args):
+    xm.main(args)
diff --git a/tools/xen/lib/xm/opts.py b/tools/xen/lib/xm/opts.py
new file mode 100644 (file)
index 0000000..5b95152
--- /dev/null
@@ -0,0 +1,339 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Object-oriented command-line option support.
+"""
+from getopt import getopt
+import os
+import os.path
+import sys
+import types
+
+class Opt:
+    """An individual option.
+    """
+    def __init__(self, opts, name, short=None, long=None,
+                 val=None, fn=None, use=None, default=None):
+        """Create an option.
+
+        opts    parent options object
+        name    name of the field it controls
+        short   short (1-char) command line switch (optional)
+        long    long command-line switch. Defaults to option name.
+        val     string used to print option args in help.
+                If val is not specified the option has no arg.
+        fn      function to call when the option is specified.
+        use     usage (help) string
+        default default value if not specified on command-line
+        """
+        self.opts = opts
+        self.name = name
+        self.short = short
+        if long is None:
+            long = name
+        self.long = long
+        self.val = val
+        self.use = use
+        self.default = default
+        self.optkeys = []
+        if self.short:
+            self.optkeys.append('-' + self.short)
+        if self.long:
+            self.optkeys.append('--' + self.long)
+        self.fn = fn
+        self.specified_opt = None
+        self.specified_val = None
+        self.value = None
+        self.set(default)
+
+    def __repr__(self):
+        return self.name + '=' + str(self.specified_val)
+
+    __str__ = __repr__
+
+    def set(self, value):
+        """Set the option value.
+        """
+        self.opts.setopt(self.name, value)
+
+    def get(self):
+        """Get the option value.
+        """
+        return self.opts.getopt(self.name)
+
+    def append(self, value):
+        """Append a value to the option value.
+        """
+        v = self.get() or []
+        v.append(value)
+        self.set(v)
+
+    def short_opt(self):
+        """Short option spec.
+        """
+        if self.short:
+            if self.val:
+                return self.short + ':'
+            else:
+                return self.short
+        else:
+            return None
+
+    def long_opt(self):
+        """Long option spec.
+        """
+        if self.long:
+            if self.val:
+                return self.long + '='
+            else:
+                return self.long
+        else:
+            return None
+
+    def show(self):
+        sep = ''
+        for x in self.optkeys:
+            print sep, x,
+            sep = ','
+        if self.val:
+            print self.val,
+        print
+        if self.use:
+            print '\t',
+            print self.use
+        if self.val:
+            print '\tDefault', self.default or 'None'
+
+    def specify(self, k, v):
+        """Specify the option. Called when the option is set
+        from the command line.
+
+        k  option switch used
+        v  optional value given (if any)
+        """
+        if k in self.optkeys:
+            if self.val is None and v:
+                self.opts.err("Option '%s' does not take a value" % k)
+            self.specified_opt = k
+            self.specified_val = v
+            if self.fn:
+                self.fn(self, k, v)
+            return 1
+        else:
+            return 0
+
+    def specified(self):
+        """Test whether the option has been specified: set
+        from the command line.
+        """
+        return self.specified_opt
+
+class OptVals:
+    """Class to hold option values.
+    """
+    pass
+
+class Opts:
+    """Container for options.
+    """
+    def __init__(self, use=None):
+        """Options constructor.
+
+        use  usage string
+        """
+        self.use = use
+        # List of options.
+        self.options = []
+        # Options indexed by name.
+        self.options_map = {}
+        # Command-line arguments.
+        self.argv = []
+        # Option values.
+        self.vals = OptVals()
+        self.vals.quiet = 0
+        # Variables for default scripts.
+        self.vars = {}
+
+    def __repr__(self):
+        return '\n'.join(map(str, self.options))
+
+    __str__ = __repr__
+
+    def opt(self, name, **args):
+        """Add an option.
+
+        name    option name
+        **args  keyword params for option constructor
+        """
+        x = Opt(self, name, **args)
+        self.options.append(x)
+        self.options_map[name] = x
+        return x
+
+    def setvar(self, var, val):
+        """Set a default script variable.
+        """
+        self.vars[var] = val
+
+    def getvar(self, var):
+        """Get a default script variable.
+        """
+        return self.vars.get(var)
+
+    def option(self, name):
+        """Get an option (object).
+        """
+        return self.options_map.get(name)
+
+    def setopt(self, name, val):
+        """Set an option value.
+        An option can also be set using 'opts.vals.name = val'.
+        """
+        setattr(self.vals, name, val)
+
+    def getopt(self, name):
+        """Get an option value.
+        An option value can also be got using 'opts.vals.name'.
+        """
+        getattr(self.vals, name)
+
+    def specified(self, name):
+        """Test if an option has been specified.
+        """
+        opt = self.option(name)
+        return opt and opt.specified()
+
+    def err(self, msg):
+        """Print an error to stderr and exit.
+        """
+        print >>sys.stderr, "Error:", msg
+        sys.exit(1)
+
+    def info(self, msg):
+        """Print a message to stdout (unless quiet is set).
+        """
+        if self.vals.quiet: return
+        print msg
+
+    def warn(self, msg):
+        """Print a warning to stdout.
+        """
+        print >>sys.stderr, "Warning:", msg
+
+    def parse(self, argv):
+        """Parse arguments argv using the options.
+
+        return remaining arguments
+        """
+        self.argv = argv
+        (vals, args) = getopt(argv[1:], self.short_opts(), self.long_opts())
+        self.args = args
+        for (k, v) in vals:
+            for opt in self.options:
+                if opt.specify(k, v): break
+            else:
+                print >>sys.stderr, "Error: Unknown option:", k
+                self.usage()
+        return args
+
+    def short_opts(self):
+        """Get short options specifier for getopt.
+        """
+        l = []
+        for x in self.options:
+            y = x.short_opt()
+            if not y: continue
+            l.append(y)
+        return ''.join(l)
+
+    def long_opts(self):
+        """Get long options specifier for getopt.
+        """
+        l = []
+        for x in self.options:
+            y = x.long_opt()
+            if not y: continue
+            l.append(y)
+        return l
+
+    def usage(self):
+        print 'Usage: ', self.argv[0], self.use or 'OPTIONS'
+        for opt in self.options:
+            opt.show()
+
+    def load_defaults(self):
+        """Load a defaults script. Assumes these options set:
+        'path'    search path
+        'default' script name
+        """
+        for x in [ '' ] + self.vals.path.split(':'):
+            if x:
+                p = os.path.join(x, self.vals.defaults)
+            else:
+                p = self.vals.defaults
+            if os.path.exists(p):
+                self.load(p)
+                break
+        else:
+            self.err("Cannot open defaults file %s" % self.vals.defaults)
+
+    def load(self, defaults, help=0):
+        """Load a defaults file. Local variables in the file
+        are used to set options with the same names.
+        Variables are not used to set options that are already specified.
+        """
+        # Create global and lobal dicts for the file.
+        # Initialize locals to the vars.
+        # Use exec to do the standard imports and
+        # define variables we are passing to the script.
+        globals = {}
+        locals = {}
+        locals.update(self.vars)
+        cmd = '\n'.join(["import sys",
+                         "import os",
+                         "import os.path",
+                         "xm_file = '%s'" % defaults,
+                         "xm_help = %d" % help ])
+        exec cmd in globals, locals
+        execfile(defaults, globals, locals)
+        if help: return
+        # Extract the values set by the script and set the corresponding
+        # options, if not set on the command line.
+        vtypes = [ types.StringType,
+                   types.ListType,
+                   types.IntType,
+                   types.FloatType
+                   ]
+        for (k, v) in locals.items():
+            if self.specified(k): continue
+            if not(type(v) in vtypes): continue
+            self.setopt(k, v)
+
+def set_true(opt, k, v):
+    """Set an option true."""
+    opt.set(1)
+
+def set_false(opt, k, v):
+    """Set an option false."""
+    opt.set(0)
+
+def set_value(opt, k, v):
+    """Set an option to a valoue."""
+    opt.set(v)
+
+def set_int(opt, k, v):
+    """Set an option to an integer value."""
+    try:
+        v = int(v)
+    except:
+        opt.opts.err('Invalid value: ' + str(v))
+    opt.set(v)
+
+def append_value(opt, k, v):
+    """Append a value to a list option."""
+    opt.append(v)
+
+def set_var(opt, k, v):
+    """Set a default script variable.
+    """
+    (var, val) = v.strip().split('=')
+    opt.opts.setvar(var.strip(), val.strip())
+
diff --git a/tools/xen/lib/xm/shutdown.py b/tools/xen/lib/xm/shutdown.py
new file mode 100644 (file)
index 0000000..7dc8100
--- /dev/null
@@ -0,0 +1,75 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Domain shutdown.
+"""
+import string
+import sys
+import time
+
+from xen.xend.XendClient import server
+from xen.xend.xm.opts import *
+
+gopts = Opts(use="""[options] [DOM]
+
+Shutdown one or more domains gracefully.""")
+
+gopts.opt('help', short='h',
+         fn=set_true, default=0,
+         use="Print this help.")
+
+gopts.opt('all', short='a',
+         fn=set_true, default=0,
+         use="Shutdown all domains.")
+
+gopts.opt('wait', short='w',
+         fn=set_true, default=0,
+         use='Wait for shutdown to complete.')
+
+gopts.opt('norestart', short='n',
+          fn=set_true, default=0,
+          use='Prevent domain restart.')
+
+def shutdown(opts, doms, wait):
+    def domains():
+        return [ int(a) for a in server.xend_domains() ]
+    if doms == None: doms = domains()
+    if 0 in doms:
+        doms.remove(0)
+    for d in doms:
+        server.xend_domain_shutdown(d)
+    if wait:
+        while doms:
+            alive = domains()
+            dead = []
+            for d in doms:
+                if d in alive: continue
+                dead.append(d)
+            for d in dead:
+                opts.info("Domain %d terminated" % d)
+                doms.remove(d)
+            time.sleep(1)
+        opts.info("All domains terminated")
+
+def main_all(opts, args):
+    shutdown(opts, None, opts.vals.wait)
+
+def main_dom(opts, args):
+    if len(args) < 1: opts.err('Missing domain')
+    dom = args[0]
+    try:
+        domid = int(dom)
+    except:
+        opts.err('Invalid domain: ' + dom)
+    shutdown(opts, [ domid ], opts.vals.wait)
+    
+def main(argv):
+    opts = gopts
+    args = opts.parse(argv)
+    if opts.vals.help:
+        opts.usage()
+        return
+    print 'shutdown.main>', len(args), args
+    if opts.vals.all:
+        main_all(opts, args)
+    else:
+        main_dom(opts, args)
+        
diff --git a/tools/xen/netfix b/tools/xen/netfix
new file mode 100644 (file)
index 0000000..def4e28
--- /dev/null
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+#  -*- mode: python; -*-
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+#============================================================================
+# Move the IP address from eth0 onto the Xen bridge (nbe-br).
+# Only works if the bridge control utils (brctl) have been installed.
+#============================================================================
+
+from getopt import getopt
+from xen.xend.XendBridge import *
+
+short_options = 'hvqni:b:c'
+long_options  = ['help', 'verbose', 'quiet',
+                 'interface=', 'bridge=', 'create']
+
+def usage():
+    print """Usage:
+    %s [options]
+
+    Reconfigure routing so that <bridge> has the IP address from
+    <interface>. This lets IP carry on working when <interface>
+    is attached to <bridge> for virtual networking.
+    Uses brctl to add <interface> to <bridge>,
+    so this can be run before any domains have been created.
+    """ % sys.argv[0]
+    print """
+    -i, --interface <interface>    interface, default %(interface)s.
+    -b, --bridge <bridge>          bridge, default %(bridge)s.
+    -c, --create                   create the bridge.
+    -v, --verbose                  Print commands.
+    -q, --quiet                    Don't print commands.
+    -n, --dry-run                  Don't execute commands.
+    -h, --help                     Print this help.
+    """ % defaults
+    sys.exit(1)
+
+
+def main():
+    lopts = set_opts(Opts(defaults))
+    lopts.dryrun = 0
+    (options, args) = getopt(sys.argv[1:], short_options, long_options)
+    if args: usage()
+    for k, v in options:
+        if k in ['-h', '--help']:
+            usage()
+        elif k in ['-c', '--create']:
+            lopts.create = 1
+        elif k in ['-i', '--interface']:
+            lopts.interface = v
+        elif k in ['-b', '--bridge']:
+            lopts.bridge = v
+        elif k in ['-q', '--quiet']:
+            lopts.verbose = 0
+        elif k in ['-v', '--verbose']:
+            lopts.verbose = 1
+        elif k in ['-n', '--dry-run']:
+            lopts.dryrun = 1
+    reconfigure(lopts.interface, lopts.bridge)
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/xen/setup.py b/tools/xen/setup.py
new file mode 100644 (file)
index 0000000..e099e00
--- /dev/null
@@ -0,0 +1,16 @@
+
+from distutils.core import setup, Extension
+
+setup(name            = 'xen',
+      version         = '1.0',
+      description     = 'Xen',
+      author          = 'Mike Wray',
+      author_email    = 'mike.wray@hp.com',
+      packages        = ['xen',
+                         'xen.ext',
+                         'xen.xend',
+                         'xen.xend.server',
+                         'xen.xm',
+                         ],
+      package_dir     = { 'xen': 'lib' },
+      )
diff --git a/tools/xen/xend b/tools/xen/xend
new file mode 100644 (file)
index 0000000..65cfe8d
--- /dev/null
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+#  -*- mode: python; -*-
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Xen management daemon. Lives in /usr/sbin.
+   Provides console server and HTTP management api.
+
+   Run:
+
+   xend start
+
+   The daemon is stopped with:
+
+   xend stop
+
+   Unfortunately restarting it upsets the channel to dom0 and
+   domain management stops working - needs a reboot to fix.
+"""
+import os
+import sys
+from xen.xend.server import SrvDaemon
+
+def main():
+    daemon = SrvDaemon.instance()
+    if not sys.argv[1:]:
+        print 'usage: %s {start|stop|restart}' % sys.argv[0]
+    elif os.fork():
+        pid, status = os.wait()
+        return status >> 8
+    elif sys.argv[1] == 'start':
+        return daemon.start()
+    elif sys.argv[1] == 'stop':
+        return daemon.stop()
+    elif sys.argv[1] == 'restart':
+        return daemon.stop() or daemon.start()
+    else:
+        print 'not an option:', sys.argv[1]
+    return 1
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/tools/xen/xm b/tools/xen/xm
new file mode 100755 (executable)
index 0000000..09d8036
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/python
+#  -*- mode: python; -*-
+import sys
+from xen.xm import main
+
+main.main(sys.argv)
diff --git a/tools/xend-old/Makefile b/tools/xend-old/Makefile
new file mode 100644 (file)
index 0000000..8e28c03
--- /dev/null
@@ -0,0 +1,17 @@
+
+all:
+       python setup.py build
+
+install: all
+       if [ "$(prefix)" = "" ]; then                   \
+           python setup.py install;                    \
+       elif [ "$(dist)" = "yes" ]; then                \
+           python setup.py install --home="$(prefix)"; \
+       else                                            \
+           python setup.py install --root="$(prefix)"; \
+       fi
+       mkdir -p $(prefix)/usr/sbin
+       install -m0755 xend $(prefix)/usr/sbin
+
+clean:
+       rm -rf build *.pyc *.pyo *.a *.so *.o *~ *.rpm 
diff --git a/tools/xend-old/lib/__init__.py b/tools/xend-old/lib/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/xend-old/lib/blkif.py b/tools/xend-old/lib/blkif.py
new file mode 100644 (file)
index 0000000..51431b6
--- /dev/null
@@ -0,0 +1,214 @@
+
+#################################################################
+## xend/blkif.py -- Block-interface management functions for Xend
+## Copyright (c) 2004, K A Fraser (University of Cambridge)
+#################################################################
+
+import errno, re, os, select, signal, socket, sys
+import xend.main, xend.console, xend.manager, xend.utils, Xc
+
+CMSG_BLKIF_BE = 1
+CMSG_BLKIF_FE = 2
+CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
+CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
+CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED    = 32
+CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
+CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
+CMSG_BLKIF_BE_CREATE      = 0
+CMSG_BLKIF_BE_DESTROY     = 1
+CMSG_BLKIF_BE_CONNECT     = 2
+CMSG_BLKIF_BE_DISCONNECT  = 3
+CMSG_BLKIF_BE_VBD_CREATE  = 4
+CMSG_BLKIF_BE_VBD_DESTROY = 5
+CMSG_BLKIF_BE_VBD_GROW    = 6
+CMSG_BLKIF_BE_VBD_SHRINK  = 7
+
+BLKIF_DRIVER_STATUS_DOWN  = 0
+BLKIF_DRIVER_STATUS_UP    = 1
+
+pendmsg = None
+pendaddr = None
+
+recovery = False # Is a recovery in progress? (if so we'll need to notify guests)
+be_port  = None  # Port object for backend domain
+
+def backend_tx_req(msg):
+    port = xend.blkif.be_port
+    if not port:
+        print "BUG: attempt to transmit request to non-existant blkif driver"
+    if port.space_to_write_request():
+        port.write_request(msg)
+        port.notify()
+    else:
+        xend.blkif.pendmsg = msg
+
+def backend_rx_req(port, msg):
+    port.write_response(msg)
+    subtype = (msg.get_header())['subtype']
+    print "Received blkif-be request, subtype %d" % subtype
+    if subtype == CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
+        status = (msg.get_payload())['status']
+        if status == BLKIF_DRIVER_STATUS_UP:
+            if xend.blkif.recovery:
+                # Nasty hack: we count the number of VBDs we reattach so that
+                # we'll know when to notify the guests.  Must make this better!
+                interface.rebuilt_so_far = 0
+                interface.nr_to_rebuild  = 0
+                print "New blkif backend now UP, rebuilding VBDs:"
+                for blkif_key in interface.list.keys():
+                    blkif = interface.list[blkif_key]
+                    blkif.create()
+                    for vdev in blkif.devices.keys():
+                        blkif.reattach_device(vdev)
+                        interface.nr_to_rebuild += 1
+        else:
+            print "Unexpected block backend driver status: %d" % status
+
+
+def backend_rx_rsp(port, msg):
+    subtype = (msg.get_header())['subtype']
+    print "Received blkif-be response, subtype %d" % subtype
+    if subtype == CMSG_BLKIF_BE_CREATE:
+        rsp = { 'success': True }
+        xend.main.send_management_response(rsp, xend.blkif.pendaddr)
+    elif subtype == CMSG_BLKIF_BE_CONNECT:
+        pl = msg.get_payload()
+        (dom, hnd, frame, evtchn, st) = (pl['domid'], pl['blkif_handle'],
+                                         pl['shmem_frame'], pl['evtchn'],
+                                         pl['status'])
+        blkif = interface.list[xend.main.port_from_dom(dom).local_port]
+        msg = xend.utils.message(CMSG_BLKIF_FE,
+                                 CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED, 0,
+                                 { 'handle' : 0, 'status' : 2,
+                                   'evtchn' : blkif.evtchn['port2'] })
+        blkif.ctrlif_tx_req(xend.main.port_list[blkif.key], msg)
+    elif subtype == CMSG_BLKIF_BE_VBD_CREATE:
+        pl = msg.get_payload()
+        (dom, hnd, vdev, ro, st) = (pl['domid'], pl['blkif_handle'],
+                                    pl['vdevice'], pl['readonly'],
+                                    pl['status'])
+        blkif = interface.list[xend.main.port_from_dom(dom).local_port]
+        (pdev, start_sect, nr_sect, readonly) = blkif.devices[vdev]
+        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW, 0,
+                                 { 'domid' : dom, 'blkif_handle' : 0,
+                                   'vdevice' : vdev,
+                                   'extent.sector_start' : start_sect,
+                                   'extent.sector_length' : nr_sect,
+                                   'extent.device' : pdev })
+        backend_tx_req(msg)
+    elif subtype == CMSG_BLKIF_BE_VBD_GROW:
+       if not xend.blkif.recovery:
+           rsp = { 'success': True }
+           xend.main.send_management_response(rsp, xend.blkif.pendaddr)
+       else:
+           interface.rebuilt_so_far += 1
+           if interface.rebuilt_so_far == interface.nr_to_rebuild:
+               print "Rebuilt VBDs, notifying guests:"
+               for blkif_key in interface.list.keys():
+                   blkif = interface.list[blkif_key]
+                   print "  Notifying %d" % blkif.dom
+                   msg = xend.utils.message(CMSG_BLKIF_FE,
+                                            CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED,
+                                            0, { 'handle' : 0, 'status' : 1 })
+                   blkif.ctrlif_tx_req(xend.main.port_from_dom(blkif.dom),msg)
+               xend.blkif.recovery = False
+               print "Done notifying guests"
+
+
+def backend_do_work(port):
+    global pendmsg
+    if pendmsg and port.space_to_write_request():
+        port.write_request(pendmsg)
+        pendmsg = None
+        return True
+    return False
+
+
+class interface:
+
+    # Dictionary of all block-device interfaces.
+    list = {}
+
+    # NB. 'key' is an opaque value that has no meaning in this class.
+    def __init__(self, dom, key):
+        self.dom     = dom
+        self.key     = key
+        self.devices = {}
+        self.pendmsg = None
+        interface.list[key] = self
+        self.create()
+
+    def create(self):
+        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE, 0,
+                                 { 'domid' : self.dom, 'blkif_handle' : 0 })
+        xend.blkif.pendaddr = xend.main.mgmt_req_addr
+        backend_tx_req(msg)
+
+    # Attach a device to the specified interface
+    def attach_device(self, vdev, pdev, start_sect, nr_sect, readonly):
+        if self.devices.has_key(vdev):
+            return False
+        self.devices[vdev] = (pdev, start_sect, nr_sect, readonly)
+        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE, 0,
+                                 { 'domid' : self.dom, 'blkif_handle' : 0,
+                                   'vdevice' : vdev, 'readonly' : readonly })
+        xend.blkif.pendaddr = xend.main.mgmt_req_addr
+        backend_tx_req(msg)
+        return True
+
+    def reattach_device(self, vdev):
+        (pdev, start_sect, nr_sect, readonly) = self.devices[vdev]
+        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE,
+                                 0, { 'domid' : self.dom,
+                                      'blkif_handle' : 0,
+                                      'vdevice' : vdev,
+                                      'readonly' : readonly })
+        xend.blkif.pendaddr = xend.main.mgmt_req_addr
+        backend_tx_req(msg)
+
+    # Completely destroy this interface.
+    def destroy(self):
+        del interface.list[self.key]
+        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY, 0,
+                                 { 'domid' : self.dom, 'blkif_handle' : 0 })
+        backend_tx_req(msg)        
+
+
+    # The parameter @port is the control-interface event channel. This method
+    # returns True if messages were written to the control interface.
+    def ctrlif_transmit_work(self, port):
+        if self.pendmsg and port.space_to_write_request():
+            port.write_request(self.pendmsg)
+            self.pendmsg = None
+            return True
+        return False
+
+    def ctrlif_tx_req(self, port, msg):
+        if port.space_to_write_request():
+            port.write_request(msg)
+            port.notify()
+        else:
+            self.pendmsg = msg
+
+    def ctrlif_rx_req(self, port, msg):
+        port.write_response(msg)
+        subtype = (msg.get_header())['subtype']
+        if subtype == CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
+            msg = xend.utils.message(CMSG_BLKIF_FE,
+                                     CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED,
+                                     0,
+                                     { 'handle' : 0, 'status' : 1 })
+            self.ctrlif_tx_req(port, msg)
+        elif subtype == CMSG_BLKIF_FE_INTERFACE_CONNECT:
+            pl = msg.get_payload()
+            (hnd, frame) = (pl['handle'], pl['shmem_frame'])
+            xc = Xc.new()
+            self.evtchn = xc.evtchn_bind_interdomain(
+                                            dom1=xend.blkif.be_port.remote_dom,
+                                            dom2=self.dom)
+            msg = xend.utils.message(CMSG_BLKIF_BE,
+                                     CMSG_BLKIF_BE_CONNECT, 0,
+                                     { 'domid' : self.dom, 'blkif_handle' : 0,
+                                       'shmem_frame' : frame,
+                                       'evtchn' : self.evtchn['port1'] })
+            backend_tx_req(msg)
diff --git a/tools/xend-old/lib/console.py b/tools/xend-old/lib/console.py
new file mode 100644 (file)
index 0000000..5789881
--- /dev/null
@@ -0,0 +1,180 @@
+
+#############################################################
+## xend/console.py -- Console-management functions for Xend
+## Copyright (c) 2004, K A Fraser (University of Cambridge)
+#############################################################
+
+import errno, re, os, select, signal, socket, struct, sys
+import xend.blkif, xend.main, xend.manager, xend.utils, Xc
+
+##
+## interface:
+##  Each control interface owns an instance of this class, which manages
+##  the current state of the console interface. Normally a console interface
+##  will be one of two state:
+##   LISTENING: listening for a connection on TCP port 'self.port'
+##   CONNECTED: sending/receiving console data on TCP port 'self.port'
+##
+##  A dictionary of all active interfaces, indexed by TCP socket descriptor,
+##  is accessible as 'interface.list_by_fd'.
+##
+##  NB. When a class instance is to be destroyed you *must* call the 'close'
+##  method. Otherwise a stale reference will eb left in the interface list.
+##
+class interface:
+
+    # The various states that a console interface may be in.
+    CLOSED    = 0 # No console activity
+    LISTENING = 1 # Listening on port 'self.port'. Socket object 'self.sock'.
+    CONNECTED = 2 # Active connection on 'self.port'. Socket obj 'self.sock'.
+
+
+    # Dictionary of all active (non-closed) console interfaces.
+    list_by_fd = {}
+
+
+    # Dictionary of all console interfaces, closed and open.
+    list = {}
+
+
+    # NB. 'key' is an opaque value that has no meaning in this class.
+    def __init__(self, port, key):
+        self.status = interface.CLOSED
+        self.port   = port
+        self.key    = key
+        self.rbuf   = xend.utils.buffer()
+        self.wbuf   = xend.utils.buffer()
+        interface.list[key] = self
+
+
+    # Is this interface closed (inactive)?
+    def closed(self):
+        return self.status == interface.CLOSED
+
+
+    # Is this interface listening?
+    def listening(self):
+        return self.status == interface.LISTENING
+
+
+    # Is this interface active and connected?
+    def connected(self):
+        return self.status == interface.CONNECTED
+
+
+    # Close the interface, if it is not closed already.
+    def close(self):
+        if not self.closed():
+            del interface.list_by_fd[self.sock.fileno()]
+            self.sock.close()
+            del self.sock
+            self.status = interface.CLOSED
+
+
+    # Move the interface into the 'listening' state. Opens a new listening
+    # socket and updates 'list_by_fd'.
+    def listen(self):
+        # Close old socket (if any), and create a fresh one.
+        self.close()
+        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+
+        try:
+            # Turn the new socket into a non-blocking listener.
+            self.sock.setblocking(False)
+            self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+            self.sock.bind(('', self.port))
+            self.sock.listen(1)
+
+            # Announce the new status of thsi interface.
+            self.status = interface.LISTENING
+            interface.list_by_fd[self.sock.fileno()] = self
+
+        except:
+            # In case of trouble ensure we get rid of dangling socket reference
+            self.sock.close()
+            del self.sock
+            raise
+
+
+    # Move a listening interface into the 'connected' state.
+    def connect(self):
+        # Pick up a new connection, if one is available.
+        try:
+            (sock, addr) = self.sock.accept()
+        except:
+            return 0
+        sock.setblocking(False)
+        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+
+        # Close the listening socket.
+        self.sock.close()
+
+        # Publish the new socket and the new interface state.
+        self.sock = sock
+        self.status = interface.CONNECTED
+        interface.list_by_fd[self.sock.fileno()] = self
+        return 1
+
+
+    # Completely sestroy a console interface.
+    def destroy(self):
+        self.close()
+        del interface.list[self.key]
+
+
+    # Do work triggered by resource availability on a console-interface socket.
+    def socket_work(self):
+        # If the interface is listening, check for pending connections.
+        if self.listening():
+            self.connect()
+
+        # All done if the interface is not connected.
+        if not self.connected():
+            return
+
+        # Send as much pending data as possible via the socket.
+        while not self.rbuf.empty():
+            try:
+                bytes = self.sock.send(self.rbuf.peek())
+                if bytes > 0:
+                    self.rbuf.discard(bytes)
+            except socket.error, error:
+                pass
+
+        # Read as much data as is available. Don't worry about
+        # overflowing our buffer: it's more important to read the
+        # incoming data stream and detect errors or closure of the
+        # remote end in a timely manner.
+        try:
+            while 1:
+                data = self.sock.recv(2048)
+                # Return of zero means the remote end has disconnected.
+                # We therefore return the console interface to listening.
+                if not data:
+                    self.listen()
+                    break
+                self.wbuf.write(data)
+        except socket.error, error:
+            # Assume that most errors mean that the connection is dead.
+            # In such cases we return the interface to 'listening' state.
+            if error[0] != errno.EAGAIN:
+                print "Better return to listening"
+                self.listen()
+                print "New status: " + str(self.status)
+
+
+    # The parameter @port is the control-interface event channel. This method
+    # returns True if messages were written to the control interface.
+    def ctrlif_transmit_work(self, port):
+        work_done = False
+        while not self.wbuf.empty() and port.space_to_write_request():
+            msg = xend.utils.message(0, 0, 0)
+            msg.append_payload(self.wbuf.read(msg.MAX_PAYLOAD))
+            port.write_request(msg)
+            work_done = True
+        return work_done
+
+
+    def ctrlif_rx_req(self, port, msg):
+        self.rbuf.write(msg.get_payload())
+        port.write_response(msg)
diff --git a/tools/xend-old/lib/domain_controller.h b/tools/xend-old/lib/domain_controller.h
new file mode 100644 (file)
index 0000000..76dd164
--- /dev/null
@@ -0,0 +1,532 @@
+/******************************************************************************
+ * domain_controller.h
+ * 
+ * Interface to server controller (e.g., 'xend'). This header file defines the 
+ * interface that is shared with guest OSes.
+ * 
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __DOMAIN_CONTROLLER_H__
+#define __DOMAIN_CONTROLLER_H__
+
+
+#ifndef BASIC_START_INFO
+#error "Xen header file hypervisor-if.h must already be included here."
+#endif
+
+
+/*
+ * EXTENDED BOOTSTRAP STRUCTURE FOR NEW DOMAINS.
+ */
+
+typedef struct {
+    BASIC_START_INFO;
+    u16 domain_controller_evtchn; /* 320 */
+} PACKED extended_start_info_t; /* 322 bytes */
+#define SIF_BLK_BE_DOMAIN (1<<4)  /* Is this a block backend domain? */
+#define SIF_NET_BE_DOMAIN (1<<5)  /* Is this a net backend domain? */
+
+
+/*
+ * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
+ * interpreted by control software to determine the appropriate action. These 
+ * are only really advisories: the controller can actually do as it likes.
+ */
+#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
+#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
+#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
+
+
+/*
+ * CONTROLLER MESSAGING INTERFACE.
+ */
+
+typedef struct {
+    u8 type;     /*  0: echoed in response */
+    u8 subtype;  /*  1: echoed in response */
+    u8 id;       /*  2: echoed in response */
+    u8 length;   /*  3: number of bytes in 'msg' */
+    u8 msg[60];  /*  4: type-specific message data */
+} PACKED control_msg_t; /* 64 bytes */
+
+#define CONTROL_RING_SIZE 8
+typedef u32 CONTROL_RING_IDX;
+#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
+
+typedef struct {
+    control_msg_t tx_ring[CONTROL_RING_SIZE];   /*    0: guest -> controller */
+    control_msg_t rx_ring[CONTROL_RING_SIZE];   /*  512: controller -> guest */
+    CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
+    CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
+} PACKED control_if_t; /* 1040 bytes */
+
+/*
+ * Top-level command types.
+ */
+#define CMSG_CONSOLE        0  /* Console                 */
+#define CMSG_BLKIF_BE       1  /* Block-device backend    */
+#define CMSG_BLKIF_FE       2  /* Block-device frontend   */
+#define CMSG_NETIF_BE       3  /* Network-device backend  */
+#define CMSG_NETIF_FE       4  /* Network-device frontend */
+#define CMSG_SHUTDOWN       6  /* Shutdown messages       */
+
+
+/******************************************************************************
+ * CONSOLE DEFINITIONS
+ */
+
+/*
+ * Subtypes for console messages.
+ */
+#define CMSG_CONSOLE_DATA       0
+
+
+/******************************************************************************
+ * BLOCK-INTERFACE FRONTEND DEFINITIONS
+ */
+
+/* Messages from domain controller to guest. */
+#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED   0
+
+/* Messages from guest to domain controller. */
+#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
+#define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
+#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
+
+/* These are used by both front-end and back-end drivers. */
+#define blkif_vdev_t   u16
+#define blkif_pdev_t   u16
+#define blkif_sector_t u64
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
+ *  Notify a guest about a status change on one of its block interfaces.
+ *  If the interface is DESTROYED or DOWN then the interface is disconnected:
+ *   1. The shared-memory frame is available for reuse.
+ *   2. Any unacknowledged messgaes pending on the interface were dropped.
+ */
+#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
+#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
+#define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
+typedef struct {
+    u32 handle; /*  0 */
+    u32 status; /*  4 */
+    u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
+} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
+
+/*
+ * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the front-end driver is DOWN or UP.
+ *  When the driver goes DOWN then the controller will send no more
+ *  status-change notifications. When the driver comes UP then the controller
+ *  will send a notification for each interface that currently exists.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically take the interfaces DOWN.
+ */
+#define BLKIF_DRIVER_STATUS_DOWN   0
+#define BLKIF_DRIVER_STATUS_UP     1
+typedef struct {
+    /* IN */
+    u32 status;        /*  0: BLKIF_DRIVER_STATUS_??? */
+    /* OUT */
+    /*
+     * Tells driver how many interfaces it should expect to immediately
+     * receive notifications about.
+     */
+    u32 nr_interfaces; /*  4 */
+} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_CONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_CONNECTED message.
+ */
+typedef struct {
+    u32      handle;      /*  0 */
+    u32      __pad;
+    memory_t shmem_frame; /*  8 */
+    MEMORY_PADDING;
+} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_DISCONNECTED message.
+ */
+typedef struct {
+    u32 handle; /*  0 */
+} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * BLOCK-INTERFACE BACKEND DEFINITIONS
+ */
+
+/* Messages from domain controller. */
+#define CMSG_BLKIF_BE_CREATE      0  /* Create a new block-device interface. */
+#define CMSG_BLKIF_BE_DESTROY     1  /* Destroy a block-device interface.    */
+#define CMSG_BLKIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
+#define CMSG_BLKIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
+#define CMSG_BLKIF_BE_VBD_CREATE  4  /* Create a new VBD for an interface.   */
+#define CMSG_BLKIF_BE_VBD_DESTROY 5  /* Delete a VBD from an interface.      */
+#define CMSG_BLKIF_BE_VBD_GROW    6  /* Append an extent to a given VBD.     */
+#define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
+
+/* Messages to domain controller. */
+#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
+
+/*
+ * Message request/response definitions for block-device messages.
+ */
+
+typedef struct {
+    blkif_sector_t sector_start;   /*  0 */
+    blkif_sector_t sector_length;  /*  8 */
+    blkif_pdev_t   device;         /* 16 */
+    u16            __pad;          /* 18 */
+} PACKED blkif_extent_t; /* 20 bytes */
+
+/* Non-specific 'okay' return. */
+#define BLKIF_BE_STATUS_OKAY                0
+/* Non-specific 'error' return. */
+#define BLKIF_BE_STATUS_ERROR               1
+/* The following are specific error returns. */
+#define BLKIF_BE_STATUS_INTERFACE_EXISTS    2
+#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
+#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
+#define BLKIF_BE_STATUS_VBD_EXISTS          5
+#define BLKIF_BE_STATUS_VBD_NOT_FOUND       6
+#define BLKIF_BE_STATUS_OUT_OF_MEMORY       7
+#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    8
+#define BLKIF_BE_STATUS_MAPPING_ERROR       9
+
+/* This macro can be used to create an array of descriptive error strings. */
+#define BLKIF_BE_STATUS_ERRORS {    \
+    "Okay",                         \
+    "Non-specific error",           \
+    "Interface already exists",     \
+    "Interface not found",          \
+    "Interface is still connected", \
+    "VBD already exists",           \
+    "VBD not found",                \
+    "Out of memory",                \
+    "Extent not found for VBD",     \
+    "Could not map domain memory" }
+
+/*
+ * CMSG_BLKIF_BE_CREATE:
+ *  When the driver sends a successful response then the interface is fully
+ *  created. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_create_t; /* 12 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DESTROY:
+ *  When the driver sends a successful response then the interface is fully
+ *  torn down. The controller will send a DESTROYED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify interface to be destroyed. */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_destroy_t; /* 12 bytes */
+
+/*
+ * CMSG_BLKIF_BE_CONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  connected. The controller will send a CONNECTED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    memory_t   shmem_frame;   /*  8: Page cont. shared comms window.     */
+    MEMORY_PADDING;
+    u32        evtchn;        /* 16: Event channel for notifications.    */
+    /* OUT */
+    u32        status;        /* 20 */
+} PACKED blkif_be_connect_t;  /* 24 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DISCONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  disconnected. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_disconnect_t; /* 12 bytes */
+
+/* CMSG_BLKIF_BE_VBD_CREATE */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id for this VBD. */
+    u16        readonly;      /* 10: Non-zero -> VBD isn't writeable.    */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_create_t; /* 16 bytes */
+
+/* CMSG_BLKIF_BE_VBD_DESTROY */
+typedef struct {
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 10 */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
+
+/* CMSG_BLKIF_BE_VBD_GROW */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_extent_t extent;    /*  8: Physical extent to append to VBD.   */
+    blkif_vdev_t vdevice;     /* 28: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 30 */
+    /* OUT */
+    u32        status;        /* 32 */
+} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
+
+/* CMSG_BLKIF_BE_VBD_SHRINK */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 10 */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the back-end driver is DOWN or UP.
+ *  If the driver goes DOWN while interfaces are still UP, the controller
+ *  will automatically send DOWN notifications.
+ */
+typedef struct {
+    u32        status;        /*  0: BLKIF_DRIVER_STATUS_??? */
+} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * NETWORK-INTERFACE FRONTEND DEFINITIONS
+ */
+
+/* Messages from domain controller to guest. */
+#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
+
+/* Messages from guest to domain controller. */
+#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
+#define CMSG_NETIF_FE_INTERFACE_CONNECT         33
+#define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
+ *  Notify a guest about a status change on one of its network interfaces.
+ *  If the interface is DESTROYED or DOWN then the interface is disconnected:
+ *   1. The shared-memory frame is available for reuse.
+ *   2. Any unacknowledged messgaes pending on the interface were dropped.
+ */
+#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
+#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
+#define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
+typedef struct {
+    u32        handle; /*  0 */
+    u32        status; /*  4 */
+    u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
+    u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
+} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
+
+/*
+ * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the front-end driver is DOWN or UP.
+ *  When the driver goes DOWN then the controller will send no more
+ *  status-change notifications. When the driver comes UP then the controller
+ *  will send a notification for each interface that currently exists.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically take the interfaces DOWN.
+ */
+#define NETIF_DRIVER_STATUS_DOWN   0
+#define NETIF_DRIVER_STATUS_UP     1
+typedef struct {
+    /* IN */
+    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
+    /* OUT */
+    /*
+     * Tells driver how many interfaces it should expect to immediately
+     * receive notifications about.
+     */
+    u32        nr_interfaces; /*  4 */
+} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_CONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_CONNECTED message.
+ */
+typedef struct {
+    u32        handle;         /*  0 */
+    u32        __pad;          /*  4 */
+    memory_t   tx_shmem_frame; /*  8 */
+    MEMORY_PADDING;
+    memory_t   rx_shmem_frame; /* 16 */
+    MEMORY_PADDING;
+} PACKED netif_fe_interface_connect_t; /* 24 bytes */
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_DISCONNECTED message.
+ */
+typedef struct {
+    u32        handle;        /*  0 */
+} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * NETWORK-INTERFACE BACKEND DEFINITIONS
+ */
+
+/* Messages from domain controller. */
+#define CMSG_NETIF_BE_CREATE      0  /* Create a new net-device interface. */
+#define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
+#define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
+#define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
+
+/* Messages to domain controller. */
+#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
+
+/*
+ * Message request/response definitions for net-device messages.
+ */
+
+/* Non-specific 'okay' return. */
+#define NETIF_BE_STATUS_OKAY                0
+/* Non-specific 'error' return. */
+#define NETIF_BE_STATUS_ERROR               1
+/* The following are specific error returns. */
+#define NETIF_BE_STATUS_INTERFACE_EXISTS    2
+#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
+#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
+#define NETIF_BE_STATUS_OUT_OF_MEMORY       5
+#define NETIF_BE_STATUS_MAPPING_ERROR       6
+
+/* This macro can be used to create an array of descriptive error strings. */
+#define NETIF_BE_STATUS_ERRORS {    \
+    "Okay",                         \
+    "Non-specific error",           \
+    "Interface already exists",     \
+    "Interface not found",          \
+    "Interface is still connected", \
+    "Out of memory",                \
+    "Could not map domain memory" }
+
+/*
+ * CMSG_NETIF_BE_CREATE:
+ *  When the driver sends a successful response then the interface is fully
+ *  created. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
+    u8         mac[6];        /*  8 */
+    u16        __pad;         /* 14 */
+    /* OUT */
+    u32        status;        /* 16 */
+} PACKED netif_be_create_t; /* 20 bytes */
+
+/*
+ * CMSG_NETIF_BE_DESTROY:
+ *  When the driver sends a successful response then the interface is fully
+ *  torn down. The controller will send a DESTROYED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify interface to be destroyed. */
+    u32        netif_handle;  /*  4: ...ditto...                         */
+    /* OUT */
+    u32   status;             /*  8 */
+} PACKED netif_be_destroy_t; /* 12 bytes */
+
+/*
+ * CMSG_NETIF_BE_CONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  connected. The controller will send a CONNECTED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;          /*  0: Domain attached to new interface.   */
+    u32        netif_handle;   /*  4: Domain-specific interface handle.   */
+    memory_t   tx_shmem_frame; /*  8: Page cont. tx shared comms window.  */
+    MEMORY_PADDING;
+    memory_t   rx_shmem_frame; /* 16: Page cont. rx shared comms window.  */
+    MEMORY_PADDING;
+    u16        evtchn;         /* 24: Event channel for notifications.    */
+    u16        __pad;          /* 26 */
+    /* OUT */
+    u32        status;         /* 28 */
+} PACKED netif_be_connect_t; /* 32 bytes */
+
+/*
+ * CMSG_NETIF_BE_DISCONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  disconnected. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED netif_be_disconnect_t; /* 12 bytes */
+
+/*
+ * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the back-end driver is DOWN or UP.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically send DOWN notifications.
+ */
+typedef struct {
+    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
+} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * SHUTDOWN DEFINITIONS
+ */
+
+/*
+ * Subtypes for shutdown messages.
+ */
+#define CMSG_SHUTDOWN_POWEROFF  0   /* Clean shutdown (SHUTDOWN_poweroff).   */
+#define CMSG_SHUTDOWN_REBOOT    1   /* Clean shutdown (SHUTDOWN_reboot).     */
+#define CMSG_SHUTDOWN_SUSPEND   2   /* Create suspend info, then             */
+                                    /* SHUTDOWN_suspend.                     */
+
+#endif /* __DOMAIN_CONTROLLER_H__ */
diff --git a/tools/xend-old/lib/main.py b/tools/xend-old/lib/main.py
new file mode 100755 (executable)
index 0000000..0eecd17
--- /dev/null
@@ -0,0 +1,317 @@
+
+###########################################################
+## xend.py -- Xen controller daemon
+## Copyright (c) 2004, K A Fraser (University of Cambridge)
+###########################################################
+
+import errno, re, os, pwd, select, signal, socket, struct, sys, time
+import xend.blkif, xend.netif, xend.console, xend.manager, xend.utils, Xc
+
+
+# The following parameters could be placed in a configuration file.
+PID  = '/var/run/xend.pid'
+LOG  = '/var/log/xend.log'
+USER = 'root'
+CONTROL_DIR  = '/var/run/xend'
+UNIX_SOCK    = 'management_sock' # relative to CONTROL_DIR
+
+
+CMSG_CONSOLE  = 0
+CMSG_BLKIF_BE = 1
+CMSG_BLKIF_FE = 2
+CMSG_NETIF_BE = 3
+CMSG_NETIF_FE = 4
+
+
+def port_from_dom(dom):
+    global port_list
+    for idx, port in port_list.items():
+        if port.remote_dom == dom:
+            return port
+    return None
+
+
+def send_management_response(response, addr):
+    try:
+        response = str(response)
+        print "Mgmt_rsp[%s]: %s" % (addr, response)
+        management_interface.sendto(response, addr)
+    except socket.error, error:
+        pass
+
+
+def daemon_loop():
+    # Could we do this more nicely? The xend.manager functions need access
+    # to this global state to do their work.
+    global port_list, notifier, management_interface, mgmt_req_addr, dom0_port
+
+    # Lists of all interfaces, indexed by local event-channel port.
+    port_list = {}
+    
+    xc = Xc.new()
+
+    # Ignore writes to disconnected sockets. We clean up differently.
+    signal.signal(signal.SIGPIPE, signal.SIG_IGN)
+
+    # Construct the management interface. This is a UNIX domain socket via
+    # which we receive 'request' datagrams. Each request is a string that
+    # can be eval'ed as a Python statement. Responses can be remotely eval'ed
+    # by the requester to create a Python dictionary of result values.
+    management_interface = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0)
+    if os.path.exists(CONTROL_DIR+'/'+UNIX_SOCK):
+        os.unlink(CONTROL_DIR+'/'+UNIX_SOCK)
+    management_interface.setblocking(False)
+    management_interface.bind(CONTROL_DIR+'/'+UNIX_SOCK)
+
+    # Interface via which we receive event notifications from other guest
+    # OSes. This interface also allows us to clear/acknowledge outstanding
+    # notifications.
+    notifier = xend.utils.notifier()
+
+    # The DOM0 control interface is not set up via the management interface.
+    # Note that console messages don't come our way (actually, only driver
+    # back-ends should use the DOM0 control interface).
+    dom0_port = xend.utils.port(0)
+    xend.netif.be_port = dom0_port
+    xend.blkif.be_port = dom0_port
+    notifier.bind(dom0_port.local_port)
+    port_list[dom0_port.local_port] = dom0_port
+
+    ##
+    ## MAIN LOOP
+    ## 
+    while 1:
+
+        # Construct a poll set. We wait on:
+        #  1. Requests on the management interface.
+        #  2. Incoming event-channel notifications.
+        # Furthermore, for each active control interface:
+        #  3. Incoming console data.
+        #  4. Space for outgoing console data (if there is data to send).
+        waitset = select.poll()
+        waitset.register(management_interface, select.POLLIN)
+        waitset.register(notifier, select.POLLIN)
+        for idx, con_if in xend.console.interface.list_by_fd.items():
+            if not con_if.closed():
+                pflags = select.POLLIN
+                if not con_if.rbuf.empty() and con_if.connected():
+                    pflags = select.POLLIN | select.POLLOUT
+                waitset.register(con_if.sock.fileno(), pflags)
+
+        # Wait for something to do...
+        fdset = waitset.poll()
+        
+        # Look for messages on the management interface.
+        # These should consist of executable Python statements that call
+        # well-known management functions (e.g., new_control_interface(dom=9)).
+        try:
+            data, mgmt_req_addr = management_interface.recvfrom(2048)
+        except socket.error, error:
+            if error[0] != errno.EAGAIN:
+                raise
+        else:
+            if mgmt_req_addr:
+                # Evaluate the request in an exception-trapping sandbox.
+                try:
+                    print "Mgmt_req[%s]: %s" % (mgmt_req_addr, data)
+                    response = eval('xend.manager.'+data)
+
+                except:
+                    # Catch all exceptions and turn into an error response:
+                    #  status:          False
+                    #  error_type:      'exception'
+                    #  exception_type:  name of exception type.
+                    #  exception value: textual exception value.
+                    exc_type, exc_val = sys.exc_info()[:2]
+                    response = { 'success': False }
+                    response['error_type'] = 'exception'
+                    response['exception_type'] = str(exc_type)
+                    response['exception_value'] = str(exc_val)
+                    response = str(response)
+
+                # Try to send a response to the requester.
+                if response:
+                    send_management_response(response, mgmt_req_addr)
+                
+        # Do work for every console interface that hit in the poll set.
+        for (fd, events) in fdset:
+            if xend.console.interface.list_by_fd.has_key(fd):
+                con_if = xend.console.interface.list_by_fd[fd]
+                con_if.socket_work()
+                # We may now have pending data to send via the control
+                # interface. If so then send all we can and notify the remote.
+                port = port_list[con_if.key]
+                if con_if.ctrlif_transmit_work(port):
+                    port.notify()
+                    
+        # Process control-interface notifications from other guest OSes.
+        while 1:            
+            # Grab a notification, if there is one.
+            notification = notifier.read()
+            if not notification:
+                break
+            (idx, type) = notification
+
+            if not port_list.has_key(idx):
+                continue
+
+            port = port_list[idx]
+            work_done = False
+
+            con_if = False
+            if xend.console.interface.list.has_key(idx):
+                con_if = xend.console.interface.list[idx]
+
+            blk_if = False
+            if xend.blkif.interface.list.has_key(idx):
+                blk_if = xend.blkif.interface.list[idx]
+
+            net_if = False
+            if xend.netif.interface.list.has_key(idx):
+                net_if = xend.netif.interface.list[idx]
+
+            # If we pick up a disconnect notification then we do any necessary
+            # cleanup.
+            if type == notifier.EXCEPTION:
+                ret = xc.evtchn_status(idx)
+                if ret['status'] == 'unbound':
+                    notifier.unbind(idx)
+                    del port_list[idx], port
+                    if con_if:
+                        con_if.destroy()
+                        del con_if
+                    if blk_if:
+                        blk_if.destroy()
+                        del blk_if
+                    if net_if:
+                        net_if.destroy()
+                        del net_if
+                    continue
+
+            # Process incoming requests.
+            while port.request_to_read():
+                msg = port.read_request()
+                work_done = True
+                type = (msg.get_header())['type']
+                if type == CMSG_CONSOLE and con_if:
+                    con_if.ctrlif_rx_req(port, msg)
+                elif type == CMSG_BLKIF_FE and blk_if:
+                    blk_if.ctrlif_rx_req(port, msg)
+                elif type == CMSG_BLKIF_BE and port == xend.blkif.be_port:
+                    xend.blkif.backend_rx_req(port, msg)
+                elif type == CMSG_NETIF_FE and net_if:
+                    net_if.ctrlif_rx_req(port, msg)
+                elif type == CMSG_NETIF_BE and port == xend.netif.be_port:
+                    xend.netif.backend_rx_req(port, msg)
+                else:
+                    port.write_response(msg)
+
+            # Process incoming responses.
+            while port.response_to_read():
+                msg = port.read_response()
+                work_done = True
+                type = (msg.get_header())['type']
+                if type == CMSG_BLKIF_BE and port == xend.blkif.be_port:
+                    xend.blkif.backend_rx_rsp(port, msg)
+                elif type == CMSG_NETIF_BE and port == xend.netif.be_port:
+                    xend.netif.backend_rx_rsp(port, msg)
+
+            # Send console data.
+            if con_if and con_if.ctrlif_transmit_work(port):
+                work_done = True
+
+            # Send blkif messages.
+            if blk_if and blk_if.ctrlif_transmit_work(port):
+                work_done = True
+
+            # Send netif messages.
+            if net_if and net_if.ctrlif_transmit_work(port):
+                work_done = True
+
+            # Back-end block-device work.
+            if port == dom0_port and xend.blkif.backend_do_work(port):
+                work_done = True
+                
+            # Back-end network-device work.
+            if port == xend.netif.be_port and xend.netif.backend_do_work(port):
+                work_done = True
+                
+            # Finally, notify the remote end of any work that we did.
+            if work_done:
+                port.notify()
+
+            # Unmask notifications for this port.
+            notifier.unmask(idx)
+
+
+
+def cleanup_daemon(kill=False):
+    # No cleanup to do if the PID file is empty.
+    if not os.path.isfile(PID) or not os.path.getsize(PID):
+        return 0
+    # Read the PID of the previous invocation and search active process list.
+    pid = open(PID, 'r').read()
+    lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
+    for line in lines:
+        if re.search('^ *' + pid + '.+xend', line):
+            if not kill:
+                print "Daemon is already running (PID %d)" % int(pid)
+                return 1
+            # Old daemon is still active: terminate it.
+            os.kill(int(pid), 1)
+    # Delete the, now stale, PID file.
+    os.remove(PID)
+    return 0
+
+
+
+def start_daemon():
+    if cleanup_daemon(kill=False):
+        return 1
+
+    if not os.path.exists(CONTROL_DIR):
+        os.mkdir(CONTROL_DIR)
+
+    # Open log file. Truncate it if non-empty, and request line buffering.
+    if os.path.isfile(LOG):
+        os.rename(LOG, LOG+'.old')
+    logfile = open(LOG, 'w+', 1)
+
+    # Detach from TTY.
+    os.setsid()
+
+    # Set the UID.
+    try:
+        os.setuid(pwd.getpwnam(USER)[2])
+    except KeyError, error:
+        print "Error: no such user '%s'" % USER
+        return 1
+
+    # Ensure that zombie children are automatically reaped.
+    xend.utils.autoreap()
+
+    # Fork -- parent writes the PID file and exits.
+    pid = os.fork()
+    if pid:
+        pidfile = open(PID, 'w')
+        pidfile.write(str(pid))
+        pidfile.close()
+        return 0
+
+    # Close down standard file handles
+    try:
+        os.close(0) # stdin
+        os.close(1) # stdout
+        os.close(2) # stderr
+    except:
+        pass
+
+    # Redirect output to log file, then enter the main loop.
+    sys.stdout = sys.stderr = logfile
+    daemon_loop()
+    return 0
+
+
+
+def stop_daemon():
+    return cleanup_daemon(kill=True)
diff --git a/tools/xend-old/lib/manager.py b/tools/xend-old/lib/manager.py
new file mode 100644 (file)
index 0000000..4951758
--- /dev/null
@@ -0,0 +1,174 @@
+
+#############################################################
+## xend/manager.py -- Management-interface functions for Xend
+## Copyright (c) 2004, K A Fraser (University of Cambridge)
+#############################################################
+
+import xend.blkif, xend.netif, xend.console, xend.main, xend.utils
+
+
+##
+## new_control_interface:
+##  Create a new control interface with the specified domain @dom.
+##  The console port may also be specified; otherwise a suitable port is
+##  automatically allocated.
+##
+def new_control_interface(dom, console_port=-1):
+    # Allocate an event channel and binbd to it.
+    port = xend.utils.port(dom)
+    xend.main.notifier.bind(port.local_port)
+    
+    # If necessary, compute a suitable TCP port for console I/O.
+    if console_port < 0:
+        console_port = 9600 + port.local_port
+
+    # Create a listening console interface.
+    con_if = xend.console.interface(console_port, port.local_port)
+    con_if.listen()
+
+    # Update the master port list.
+    xend.main.port_list[port.local_port] = port
+
+    # Construct the successful response to be returned to the requester.
+    response = { 'success': True }
+    response['local_port']   = port.local_port
+    response['remote_port']  = port.remote_port
+    response['console_port'] = console_port
+    return response
+
+
+##
+## new_block_interface:
+##  Create a new block interface for the specified domain @dom.
+##
+def new_block_interface(dom, handle=-1):
+    # By default we create an interface with handle zero.
+    if handle < 0:
+        handle = 0
+
+    # We only support one interface per domain, which must have handle zero.
+    if handle != 0:
+        response = { 'success': False }
+        response['error_type'] = 'Bad handle %d (only handle 0 ' + \
+                                 'is supported)' % handle
+        return response
+
+    # Find local event-channel port associated with the specified domain.
+    port = xend.main.port_from_dom(dom)
+    if not port:
+        response = { 'success': False }
+        response['error_type'] = 'Unknown domain %d' % dom
+        return response
+
+    # The interface must not already exist.
+    if xend.blkif.interface.list.has_key(port.local_port):
+        response = { 'success': False }
+        response['error_type'] = 'Interface (dom=%d,handle=%d) already ' + \
+                                 'exists' % (dom, handle)
+        return response
+
+    # Create the new interface. Initially no virtual devices are attached.
+    xend.blkif.interface(dom, port.local_port)
+
+    # Response is deferred until back-end driver sends acknowledgement.
+    return None
+
+
+##
+## new_block_device:
+##  Attach a new virtual block device to the specified block interface
+##  (@dom, @handle). The new device is identified by @vdev, and maps to
+##  the real block extent (@pdev, @start_sect, @nr_sect). If @readonly then
+##  write requests to @vdev will be rejected.
+##
+def new_block_device(dom, handle, vdev, pdev, start_sect, nr_sect, readonly):
+    # We only support one interface per domain, which must have handle zero.
+    if handle != 0:
+        response = { 'success': False }
+        response['error_type'] = 'Bad handle %d (only handle 0 ' + \
+                                 'is supported)' % handle
+        return response
+
+    # Find local event-channel port associated with the specified domain.
+    port = xend.main.port_from_dom(dom)
+    if not port:
+        response = { 'success': False }
+        response['error_type'] = 'Unknown domain %d' % dom
+        return response
+        
+    # The interface must exist.
+    if not xend.blkif.interface.list.has_key(port.local_port):
+        response = { 'success': False }
+        response['error_type'] = 'Interface (dom=%d,handle=%d) does not ' + \
+                                 'exists' % (dom, handle)
+        return response
+
+    # The virtual device must not yet exist.
+    blkif = xend.blkif.interface.list[port.local_port]
+    if not blkif.attach_device(vdev, pdev, start_sect, nr_sect, readonly):
+        response = { 'success': False }
+        response['error_type'] = 'Vdevice (dom=%d,handle=%d,vdevice=%d) ' + \
+                                 'already exists' % (dom, handle, vdev)
+        return response
+
+    # Response is deferred until back-end driver sends acknowledgement.
+    return None
+
+
+##
+## new_network_interface:
+##  Create a new network interface for the specified domain @dom.
+##
+def new_network_interface(dom, handle=-1):
+    # By default we create an interface with handle zero.
+    if handle < 0:
+        handle = 0
+
+    # We only support one interface per domain, which must have handle zero.
+    if handle != 0:
+        response = { 'success': False }
+        response['error_type'] = 'Bad handle %d (only handle 0 ' + \
+                                 'is supported)' % handle
+        return response
+
+    # Find local event-channel port associated with the specified domain.
+    port = xend.main.port_from_dom(dom)
+    if not port:
+        response = { 'success': False }
+        response['error_type'] = 'Unknown domain %d' % dom
+        return response
+
+    # The interface must not already exist.
+    if xend.netif.interface.list.has_key(port.local_port):
+        response = { 'success': False }
+        response['error_type'] = 'Interface (dom=%d,handle=%d) already ' + \
+                                 'exists' % (dom, handle)
+        return response
+
+    # Create the new interface. Initially no virtual devices are attached.
+    xend.netif.interface(dom, port.local_port)
+
+    # Response is deferred until back-end driver sends acknowledgement.
+    return None
+
+##
+## set_network_backend
+##   Authorise a domain to act as the net backend (assumes we only have one
+##   backend driver for now).  After this call, back end "up" notifications
+##   for the network will only be accepted from this domain.
+##
+def set_network_backend(dom):
+    if xend.netif.be_port.remote_dom != 0:
+        xend.netif.recovery = True
+    xend.netif.be_port = xend.main.port_from_dom(dom)
+    return { 'success' : True }
+
+##
+## set_block_backend
+##  Authorise a domain to act as the block backend (assumes we only have one
+##  backend driver for now).  After this call, back end "up" notifications
+##  for the network will only be accepted from this domain.
+def set_block_backend(dom):
+    if xend.blkif.be_port: xend.blkif.recovery = True
+    xend.blkif.be_port = xend.main.port_from_dom(dom)
+    return { 'success' : True }
diff --git a/tools/xend-old/lib/netif.py b/tools/xend-old/lib/netif.py
new file mode 100644 (file)
index 0000000..eaa1008
--- /dev/null
@@ -0,0 +1,187 @@
+
+###################################################################
+## xend/netif.py -- Network-interface management functions for Xend
+## Copyright (c) 2004, K A Fraser (University of Cambridge)
+###################################################################
+
+import errno, random, re, os, select, signal, socket, struct, sys
+import xend.main, xend.console, xend.manager, xend.utils, Xc
+
+CMSG_NETIF_BE = 3
+CMSG_NETIF_FE = 4
+CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED =  0
+CMSG_NETIF_FE_DRIVER_STATUS_CHANGED    = 32
+CMSG_NETIF_BE_DRIVER_STATUS_CHANGED    = 32
+CMSG_NETIF_FE_INTERFACE_CONNECT        = 33
+CMSG_NETIF_FE_INTERFACE_DISCONNECT     = 34
+CMSG_NETIF_BE_CREATE      = 0
+CMSG_NETIF_BE_DESTROY     = 1
+CMSG_NETIF_BE_CONNECT     = 2
+CMSG_NETIF_BE_DISCONNECT  = 3
+
+NETIF_DRIVER_STATUS_DOWN  = 0
+NETIF_DRIVER_STATUS_UP    = 1
+
+pendmsg = None
+pendaddr = None
+
+recovery = False # Is a recovery in progress?
+be_port  = None  # Port object for backend domain
+
+def backend_tx_req(msg):
+    if xend.netif.be_port.space_to_write_request():
+        xend.netif.be_port.write_request(msg)
+        xend.netif.be_port.notify()
+    else:
+        xend.netif.pendmsg = msg
+
+def backend_rx_req(port, msg):
+    port.write_response(msg)
+    subtype = (msg.get_header())['subtype']
+    print "Received netif-be request, subtype %d" % subtype
+    if subtype == CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
+        pl = msg.get_payload()
+        status = pl['status']
+        if status == NETIF_DRIVER_STATUS_UP:
+            if xend.netif.recovery:
+                print "New netif backend now UP, notifying guests:"
+                for netif_key in interface.list.keys():
+                    netif = interface.list[netif_key]
+                    netif.create()
+                    print "  Notifying %d" % netif.dom
+                    msg = xend.utils.message(
+                        CMSG_NETIF_FE,
+                        CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
+                        { 'handle' : 0, 'status' : 1 })
+                    netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom),msg)
+                print "Done notifying guests"
+                recovery = False
+        else:
+            print "Unexpected net backend driver status: %d" % status
+
+def backend_rx_rsp(port, msg):
+    subtype = (msg.get_header())['subtype']
+    print "Received netif-be response, subtype %d" % subtype
+    if subtype == CMSG_NETIF_BE_CREATE:
+        rsp = { 'success': True }
+        xend.main.send_management_response(rsp, xend.netif.pendaddr)
+    elif subtype == CMSG_NETIF_BE_CONNECT:
+        pl = msg.get_payload()
+        (dom, hnd, evtchn, tx_frame, rx_frame, st) = (
+            pl['domid'], pl['netif_handle'], pl['evtchn'],
+            pl['tx_shmem_frame'], pl['rx_shmem_frame'], pl['status'])
+        netif = interface.list[xend.main.port_from_dom(dom).local_port]
+        msg = xend.utils.message(CMSG_NETIF_FE,
+                                 CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
+                                 { 'handle' : 0, 'status' : 2,
+                                   'evtchn' : netif.evtchn['port2'],
+                                   'mac[0]' : netif.mac[0],
+                                   'mac[1]' : netif.mac[1],
+                                   'mac[2]' : netif.mac[2],
+                                   'mac[3]' : netif.mac[3],
+                                   'mac[4]' : netif.mac[4],
+                                   'mac[5]' : netif.mac[5] })
+        netif.ctrlif_tx_req(xend.main.port_list[netif.key], msg)
+
+def backend_do_work(port):
+    global pendmsg
+    if pendmsg and port.space_to_write_request():
+        port.write_request(pendmsg)
+        pendmsg = None
+        return True
+    return False
+
+
+class interface:
+
+    # Dictionary of all network-device interfaces.
+    list = {}
+
+    drvdom = None
+
+    # NB. 'key' is an opaque value that has no meaning in this class.
+    def __init__(self, dom, key):
+        self.dom     = dom
+        self.key     = key
+        self.pendmsg = None
+
+        # VIFs get a random MAC address with a "special" vendor id.
+        # 
+        # NB. The vendor is currently an "obsolete" one that used to belong
+        # to DEC (AA-00-00). Using it is probably a bit rude :-)
+        # 
+        # NB2. The first bit of the first random octet is set to zero for
+        # all dynamic MAC addresses. This may allow us to manually specify
+        # MAC addresses for some VIFs with no fear of clashes.
+        self.mac = [ 0xaa, 0x00, 0x00 ]
+        self.mac.append(int(random.random()*128))
+        self.mac.append(int(random.random()*256))
+        self.mac.append(int(random.random()*256))
+                
+        interface.list[key] = self
+        self.create()
+
+    def create(self):
+        """Notify the current network back end to create the virtual interface
+        represented by this object."""
+        msg = xend.utils.message(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE, 0,
+                                 { 'domid' : self.dom, 'netif_handle' : 0,
+                                   'mac[0]' : self.mac[0],
+                                   'mac[1]' : self.mac[1],
+                                   'mac[2]' : self.mac[2],
+                                   'mac[3]' : self.mac[3],
+                                   'mac[4]' : self.mac[4],
+                                   'mac[5]' : self.mac[5] })
+        xend.netif.pendaddr = xend.main.mgmt_req_addr
+        backend_tx_req(msg)
+
+
+    # Completely destroy this interface.
+    def destroy(self):
+        del interface.list[self.key]
+        msg = xend.utils.message(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY, 0,
+                                 { 'domid' : self.dom, 'netif_handle' : 0 })
+        backend_tx_req(msg)        
+
+
+    # The parameter @port is the control-interface event channel. This method
+    # returns True if messages were written to the control interface.
+    def ctrlif_transmit_work(self, port):
+        if self.pendmsg and port.space_to_write_request():
+            port.write_request(self.pendmsg)
+            self.pendmsg = None
+            return True
+        return False
+
+    def ctrlif_tx_req(self, port, msg):
+        if port.space_to_write_request():
+            port.write_request(msg)
+            port.notify()
+        else:
+            self.pendmsg = msg
+
+    def ctrlif_rx_req(self, port, msg):
+        port.write_response(msg)
+        subtype = (msg.get_header())['subtype']
+        if subtype == CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
+            print "netif driver up message from %d" % port.remote_dom
+            msg = xend.utils.message(CMSG_NETIF_FE,
+                                     CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
+                                     { 'handle' : 0, 'status' : 1 })
+            self.ctrlif_tx_req(port, msg)
+        elif subtype == CMSG_NETIF_FE_INTERFACE_CONNECT:
+            print "netif connect request from %d" % port.remote_dom
+            pl = msg.get_payload()
+            (hnd, tx_frame, rx_frame) = (pl['handle'], pl['tx_shmem_frame'],
+                                         pl['rx_shmem_frame'])
+            xc = Xc.new()
+            self.evtchn = xc.evtchn_bind_interdomain(
+                dom1=xend.netif.be_port.remote_dom,
+                dom2=self.dom)
+            msg = xend.utils.message(CMSG_NETIF_BE,
+                                     CMSG_NETIF_BE_CONNECT, 0,
+                                     { 'domid' : self.dom, 'netif_handle' : 0,
+                                       'tx_shmem_frame' : tx_frame,
+                                       'rx_shmem_frame' : rx_frame,
+                                       'evtchn' : self.evtchn['port1'] })
+            backend_tx_req(msg)
diff --git a/tools/xend-old/lib/utils.c b/tools/xend-old/lib/utils.c
new file mode 100644 (file)
index 0000000..2d96577
--- /dev/null
@@ -0,0 +1,1384 @@
+/******************************************************************************
+ * utils.c
+ * 
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#include <Python.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <xc.h>
+
+#include <hypervisor-if.h>
+#include "domain_controller.h"
+
+#include <asm-xen/proc_cmd.h>
+
+/* Needed for Python versions earlier than 2.3. */
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC DL_EXPORT(void)
+#endif
+
+/* NB. The following should be kept in sync with the kernel's evtchn driver. */
+#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
+#define EVTCHN_DEV_MAJOR 10
+#define EVTCHN_DEV_MINOR 200
+#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
+#define PORT_EXCEPTION  0x8000   /* An exceptional notification.        */
+#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
+/* /dev/xen/evtchn ioctls: */
+/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
+#define EVTCHN_RESET  _IO('E', 1)
+/* EVTCHN_BIND: Bind to teh specified event-channel port. */
+#define EVTCHN_BIND   _IO('E', 2)
+/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
+#define EVTCHN_UNBIND _IO('E', 3)
+
+/* Size of a machine page frame. */
+#define PAGE_SIZE 4096
+
+
+/*
+ * *********************** NOTIFIER ***********************
+ */
+
+typedef struct {
+    PyObject_HEAD;
+    int evtchn_fd;
+} xu_notifier_object;
+
+static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    u16 v;
+    int bytes;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+    
+    while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
+    {
+        if ( errno == EINTR )
+            continue;
+        if ( errno == EAGAIN )
+            goto none;
+        return PyErr_SetFromErrno(PyExc_IOError);
+    }
+    
+    if ( bytes == sizeof(v) )
+        return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK);
+
+ none:
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    u16 v;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    v = (u16)idx;
+    
+    (void)write(xun->evtchn_fd, &v, sizeof(v));
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
+        return PyErr_SetFromErrno(PyExc_IOError);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
+        return PyErr_SetFromErrno(PyExc_IOError);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    return PyInt_FromLong(xun->evtchn_fd);
+}
+
+static PyMethodDef xu_notifier_methods[] = {
+    { "read",
+      (PyCFunction)xu_notifier_read,
+      METH_VARARGS,
+      "Read a (@port, @type) pair.\n" },
+
+    { "unmask", 
+      (PyCFunction)xu_notifier_unmask,
+      METH_VARARGS,
+      "Unmask notifications for a @port.\n" },
+
+    { "bind", 
+      (PyCFunction)xu_notifier_bind,
+      METH_VARARGS,
+      "Get notifications for a @port.\n" },
+
+    { "unbind", 
+      (PyCFunction)xu_notifier_unbind,
+      METH_VARARGS,
+      "No longer get notifications for a @port.\n" },
+
+    { "fileno", 
+      (PyCFunction)xu_notifier_fileno,
+      METH_VARARGS,
+      "Return the file descriptor for the notification channel.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_notifier_type;
+
+static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
+
+ reopen:
+    xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
+    if ( xun->evtchn_fd == -1 )
+    {
+        if ( (errno == ENOENT) &&
+             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
+             (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, 
+                    (EVTCHN_DEV_MAJOR << 8) | EVTCHN_DEV_MINOR) == 0) )
+            goto reopen;
+        PyObject_Del((PyObject *)xun);
+        return PyErr_SetFromErrno(PyExc_IOError);
+    }
+
+    return (PyObject *)xun;
+}
+
+static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
+{
+    if ( strcmp(name, "EXCEPTION") == 0 )
+        return PyInt_FromLong(PORT_EXCEPTION);
+    if ( strcmp(name, "NORMAL") == 0 )
+        return PyInt_FromLong(PORT_NORMAL);
+    return Py_FindMethod(xu_notifier_methods, obj, name);
+}
+
+static void xu_notifier_dealloc(PyObject *self)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    (void)close(xun->evtchn_fd);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_notifier_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "notifier",
+    sizeof(xu_notifier_object),
+    0,
+    xu_notifier_dealloc, /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_notifier_getattr, /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** MESSAGE ***********************
+ */
+
+#define TYPE(_x,_y) (((_x)<<8)|(_y))
+#define P2C(_struct, _field, _ctype)                                      \
+    do {                                                                  \
+        PyObject *obj;                                                    \
+        if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL )     \
+        {                                                                 \
+            if ( PyInt_Check(obj) )                                       \
+            {                                                             \
+                ((_struct *)&xum->msg.msg[0])->_field =                   \
+                  (_ctype)PyInt_AsLong(obj);                              \
+                dict_items_parsed++;                                      \
+            }                                                             \
+            else if ( PyLong_Check(obj) )                                 \
+            {                                                             \
+                ((_struct *)&xum->msg.msg[0])->_field =                   \
+                  (_ctype)PyLong_AsUnsignedLongLong(obj);                 \
+                dict_items_parsed++;                                      \
+            }                                                             \
+        }                                                                 \
+        xum->msg.length = sizeof(_struct);                                \
+    } while ( 0 )
+#define C2P(_struct, _field, _pytype, _ctype)                             \
+    do {                                                                  \
+        PyObject *obj = Py ## _pytype ## _From ## _ctype                  \
+                        (((_struct *)&xum->msg.msg[0])->_field);          \
+        if ( dict == NULL ) dict = PyDict_New();                          \
+        PyDict_SetItemString(dict, #_field, obj);                         \
+    } while ( 0 )
+
+typedef struct {
+    PyObject_HEAD;
+    control_msg_t msg;
+} xu_message_object;
+
+static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    char *str;
+    int len;
+
+    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+        return NULL;
+
+    if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
+    {
+        PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
+        return NULL;
+    }
+
+    memcpy(&xum->msg.msg[xum->msg.length], str, len);
+    xum->msg.length += len;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    PyObject *payload;
+    int dict_items_parsed = 0;
+
+    if ( !PyArg_ParseTuple(args, "O", &payload) )
+        return NULL;
+
+    if ( !PyDict_Check(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
+        return NULL;
+    }
+
+    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    }
+
+    if ( dict_items_parsed != PyDict_Size(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
+        return NULL;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    PyObject *dict = NULL;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
+        C2P(blkif_fe_interface_status_changed_t, handle, Int, Long);
+        C2P(blkif_fe_interface_status_changed_t, status, Int, Long);
+        C2P(blkif_fe_interface_status_changed_t, evtchn, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
+        C2P(blkif_fe_driver_status_changed_t, status, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
+        C2P(blkif_fe_interface_connect_t, handle,      Int, Long);
+        C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
+        C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
+        C2P(blkif_be_create_t, domid,        Int, Long);
+        C2P(blkif_be_create_t, blkif_handle, Int, Long);
+        C2P(blkif_be_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
+        C2P(blkif_be_destroy_t, domid,        Int, Long);
+        C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
+        C2P(blkif_be_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
+        C2P(blkif_be_connect_t, domid,        Int, Long);
+        C2P(blkif_be_connect_t, blkif_handle, Int, Long);
+        C2P(blkif_be_connect_t, shmem_frame,  Int, Long);
+        C2P(blkif_be_connect_t, evtchn,       Int, Long);
+        C2P(blkif_be_connect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
+        C2P(blkif_be_disconnect_t, domid,        Int, Long);
+        C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
+        C2P(blkif_be_disconnect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
+        C2P(blkif_be_vbd_create_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_create_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_create_t, readonly,     Int, Long);
+        C2P(blkif_be_vbd_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
+        C2P(blkif_be_vbd_destroy_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_destroy_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
+        C2P(blkif_be_vbd_grow_t, domid,         Int, Long);
+        C2P(blkif_be_vbd_grow_t, blkif_handle,  Int, Long);
+        C2P(blkif_be_vbd_grow_t, vdevice,       Int, Long);
+        C2P(blkif_be_vbd_grow_t, extent.sector_start, 
+             Long, UnsignedLongLong);
+        C2P(blkif_be_vbd_grow_t, extent.sector_length, 
+             Long, UnsignedLongLong);
+        C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
+        C2P(blkif_be_vbd_grow_t, status,        Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
+        C2P(blkif_be_vbd_shrink_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_shrink_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_shrink_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED):
+        C2P(blkif_be_driver_status_changed_t, status, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
+        C2P(netif_fe_interface_status_changed_t, handle, Int, Long);
+        C2P(netif_fe_interface_status_changed_t, status, Int, Long);
+        C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        C2P(netif_fe_driver_status_changed_t, status,        Int, Long);
+        C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
+        C2P(netif_fe_interface_connect_t, handle,         Int, Long);
+        C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
+        C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
+        C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
+        C2P(netif_be_create_t, domid,        Int, Long);
+        C2P(netif_be_create_t, netif_handle, Int, Long);
+        C2P(netif_be_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
+        C2P(netif_be_destroy_t, domid,        Int, Long);
+        C2P(netif_be_destroy_t, netif_handle, Int, Long);
+        C2P(netif_be_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
+        C2P(netif_be_connect_t, domid,          Int, Long);
+        C2P(netif_be_connect_t, netif_handle,   Int, Long);
+        C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
+        C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
+        C2P(netif_be_connect_t, evtchn,         Int, Long);
+        C2P(netif_be_connect_t, status,         Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
+        C2P(netif_be_disconnect_t, domid,        Int, Long);
+        C2P(netif_be_disconnect_t, netif_handle, Int, Long);
+        C2P(netif_be_disconnect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED):
+        C2P(netif_be_driver_status_changed_t, status, Int, Long);
+        return dict;
+    }
+
+    return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
+}
+
+static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    return Py_BuildValue("{s:i,s:i,s:i}",
+                         "type",    xum->msg.type,
+                         "subtype", xum->msg.subtype,
+                         "id",      xum->msg.id);
+}
+
+static PyMethodDef xu_message_methods[] = {
+    { "append_payload", 
+      (PyCFunction)xu_message_append_payload,
+      METH_VARARGS,
+      "Append @str to the message payload.\n" },
+
+    { "set_response_fields",
+      (PyCFunction)xu_message_set_response_fields,
+      METH_VARARGS,
+      "Fill in the response fields in a message that was passed to us.\n" },
+
+    { "get_payload",
+      (PyCFunction)xu_message_get_payload,
+      METH_VARARGS,
+      "Return the message payload in string form.\n" },
+
+    { "get_header",
+      (PyCFunction)xu_message_get_header,
+      METH_VARARGS,
+      "Returns a dictionary of values for @type, @subtype, and @id.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_message_type;
+
+static PyObject *xu_message_new(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum;
+    int type, subtype, id, dict_items_parsed = 0;
+    PyObject *payload = NULL;
+
+    if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
+        return NULL;
+
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+
+    xum->msg.type    = type;
+    xum->msg.subtype = subtype;
+    xum->msg.id      = id;
+    xum->msg.length  = 0;
+
+    if ( payload == NULL )
+        return (PyObject *)xum;
+
+    if ( !PyDict_Check(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
+        PyObject_Del((PyObject *)xum);
+        return NULL;
+    }
+
+    switch ( TYPE(type, subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
+        P2C(blkif_fe_interface_status_changed_t, handle, u32);
+        P2C(blkif_fe_interface_status_changed_t, status, u32);
+        P2C(blkif_fe_interface_status_changed_t, evtchn, u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
+        P2C(blkif_be_create_t, domid,        u32);
+        P2C(blkif_be_create_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
+        P2C(blkif_be_destroy_t, domid,        u32);
+        P2C(blkif_be_destroy_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
+        P2C(blkif_be_connect_t, domid,        u32);
+        P2C(blkif_be_connect_t, blkif_handle, u32);
+        P2C(blkif_be_connect_t, shmem_frame,  memory_t);
+        P2C(blkif_be_connect_t, evtchn,       u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
+        P2C(blkif_be_disconnect_t, domid,        u32);
+        P2C(blkif_be_disconnect_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
+        P2C(blkif_be_vbd_create_t, domid,        u32);
+        P2C(blkif_be_vbd_create_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_create_t, vdevice,      blkif_vdev_t);
+        P2C(blkif_be_vbd_create_t, readonly,     u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
+        P2C(blkif_be_vbd_destroy_t, domid,        u32);
+        P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_destroy_t, vdevice,      blkif_vdev_t);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
+        P2C(blkif_be_vbd_grow_t, domid,                u32);
+        P2C(blkif_be_vbd_grow_t, blkif_handle,         u32);
+        P2C(blkif_be_vbd_grow_t, vdevice,              blkif_vdev_t);
+        P2C(blkif_be_vbd_grow_t, extent.sector_start,  blkif_sector_t);
+        P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
+        P2C(blkif_be_vbd_grow_t, extent.device,        blkif_pdev_t);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
+        P2C(blkif_be_vbd_shrink_t, domid,        u32);
+        P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_shrink_t, vdevice,      blkif_vdev_t);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
+        P2C(netif_fe_interface_status_changed_t, handle, u32);
+        P2C(netif_fe_interface_status_changed_t, status, u32);
+        P2C(netif_fe_interface_status_changed_t, evtchn, u16);
+        P2C(netif_fe_interface_status_changed_t, mac[0], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[1], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[2], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[3], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[4], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[5], u8);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
+        P2C(netif_be_create_t, domid,        u32);
+        P2C(netif_be_create_t, netif_handle, u32);
+        P2C(netif_be_create_t, mac[0],       u8);
+        P2C(netif_be_create_t, mac[1],       u8);
+        P2C(netif_be_create_t, mac[2],       u8);
+        P2C(netif_be_create_t, mac[3],       u8);
+        P2C(netif_be_create_t, mac[4],       u8);
+        P2C(netif_be_create_t, mac[5],       u8);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
+        P2C(netif_be_destroy_t, domid,        u32);
+        P2C(netif_be_destroy_t, netif_handle, u32);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
+        P2C(netif_be_connect_t, domid,          u32);
+        P2C(netif_be_connect_t, netif_handle,   u32);
+        P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
+        P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
+        P2C(netif_be_connect_t, evtchn,         u16);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
+        P2C(netif_be_disconnect_t, domid,        u32);
+        P2C(netif_be_disconnect_t, netif_handle, u32);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(netif_fe_driver_status_changed_t, status,        u32);
+        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    }
+
+    if ( dict_items_parsed != PyDict_Size(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
+        PyObject_Del((PyObject *)xum);
+        return NULL;
+    }
+
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_message_getattr(PyObject *obj, char *name)
+{
+    xu_message_object *xum;
+    if ( strcmp(name, "MAX_PAYLOAD") == 0 )
+        return PyInt_FromLong(sizeof(xum->msg.msg));
+    return Py_FindMethod(xu_message_methods, obj, name);
+}
+
+static void xu_message_dealloc(PyObject *self)
+{
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_message_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "message",
+    sizeof(xu_message_object),
+    0,
+    xu_message_dealloc,   /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_message_getattr,   /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** PORT ***********************
+ */
+
+static control_if_t *map_control_interface(int fd, unsigned long pfn)
+{
+    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
+                       MAP_SHARED, fd, pfn * PAGE_SIZE);
+    if ( vaddr == MAP_FAILED )
+        return NULL;
+    return (control_if_t *)(vaddr + 2048);
+}
+static void unmap_control_interface(int fd, control_if_t *c)
+{
+    char *vaddr = (char *)c - 2048;
+    (void)munmap(vaddr, PAGE_SIZE);
+}
+
+typedef struct xu_port_object {
+    PyObject_HEAD;
+    int mem_fd;
+    int xc_handle;
+    u32 remote_dom;
+    int local_port, remote_port;
+    control_if_t    *interface;
+    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
+    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
+} xu_port_object;
+
+static PyObject *port_error;
+
+static int xup_connect(xu_port_object *xup, domid_t dom,
+                       int local_port, int remote_port){
+    // From our prespective rx = producer, tx = consumer.
+    int err = 0;
+    printf("%s> dom=%u %d:%d\n", __FUNCTION__, (unsigned int)dom, 
+           local_port, remote_port);
+
+    // Consumer = tx.
+    //xup->interface->tx_resp_prod = 0;
+    //xup->interface->tx_req_prod = 0;
+    xup->tx_resp_prod = xup->interface->tx_resp_prod;
+    xup->tx_req_cons = xup->interface->tx_resp_prod;
+    printf("%s> tx: %u %u : %u %u\n", __FUNCTION__,
+           (unsigned int)xup->interface->tx_resp_prod,
+           (unsigned int)xup->tx_resp_prod,
+           (unsigned int)xup->tx_req_cons,
+           (unsigned int)xup->interface->tx_req_prod);
+
+    // Producer = rx.
+    //xup->interface->rx_req_prod  = 0;
+    //xup->interface->rx_resp_prod = 0;
+    xup->rx_req_prod  = xup->interface->rx_req_prod;
+    xup->rx_resp_cons = xup->interface->rx_resp_prod;
+    printf("%s> rx: %u %u : %u %u\n", __FUNCTION__,
+           (unsigned int)xup->rx_resp_cons,
+           (unsigned int)xup->interface->rx_resp_prod,
+           (unsigned int)xup->interface->rx_req_prod,
+           (unsigned int)xup->rx_req_prod);
+
+    xup->remote_dom   = dom;
+    xup->local_port   = local_port;
+    xup->remote_port  = remote_port;
+
+    printf("%s< err=%d\n", __FUNCTION__, err);
+    return err;
+}
+
+static PyObject *xu_port_notify(PyObject *self, PyObject *args)
+{
+    xu_port_object *xup = (xu_port_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   c = xup->tx_req_cons;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->tx_req_prod) || 
+         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
+    {
+        PyErr_SetString(port_error, "no request to read");
+        return NULL;
+    }
+
+    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+    if ( xum->msg.length > sizeof(xum->msg.msg) )
+        xum->msg.length = sizeof(xum->msg.msg);
+    xup->tx_req_cons++;
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   p = xup->rx_req_prod;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+        return NULL;
+
+    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
+    {
+        PyErr_SetString(PyExc_TypeError, "expected a xend.utils.message");
+        return NULL;        
+    }
+
+    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
+    {
+        PyErr_SetString(port_error, "no space to write request");
+        return NULL;
+    }
+
+    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
+    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
+
+    xup->rx_req_prod = cif->rx_req_prod = p + 1;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   c = xup->rx_resp_cons;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+    {
+        PyErr_SetString(port_error, "no response to read");
+        return NULL;
+    }
+
+    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+    if ( xum->msg.length > sizeof(xum->msg.msg) )
+        xum->msg.length = sizeof(xum->msg.msg);
+    xup->rx_resp_cons++;
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   p = xup->tx_resp_prod;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+        return NULL;
+
+    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
+    {
+        PyErr_SetString(PyExc_TypeError, "expected a xend.utils.message");
+        return NULL;        
+    }
+
+    if ( p == xup->tx_req_cons )
+    {
+        PyErr_SetString(port_error, "no space to write response");
+        return NULL;
+    }
+
+    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
+    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
+
+    xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   c = xup->tx_req_cons;
+    control_if_t      *cif = xup->interface;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->tx_req_prod) || 
+         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   p = xup->rx_req_prod;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   c = xup->rx_resp_cons;
+    control_if_t      *cif = xup->interface;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_response(
+    PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   p = xup->tx_resp_prod;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( p == xup->tx_req_cons )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyMethodDef xu_port_methods[] = {
+    { "notify",
+      (PyCFunction)xu_port_notify,
+      METH_VARARGS,
+      "Send a notification to the remote end.\n" },
+
+    { "read_request",
+      (PyCFunction)xu_port_read_request,
+      METH_VARARGS,
+      "Read a request message from the control interface.\n" },
+
+    { "write_request",
+      (PyCFunction)xu_port_write_request,
+      METH_VARARGS,
+      "Write a request message to the control interface.\n" },
+
+    { "read_response",
+      (PyCFunction)xu_port_read_response,
+      METH_VARARGS,
+      "Read a response message from the control interface.\n" },
+
+    { "write_response",
+      (PyCFunction)xu_port_write_response,
+      METH_VARARGS,
+      "Write a response message to the control interface.\n" },
+
+    { "request_to_read",
+      (PyCFunction)xu_port_request_to_read,
+      METH_VARARGS,
+      "Returns TRUE if there is a request message to read.\n" },
+
+    { "space_to_write_request",
+      (PyCFunction)xu_port_space_to_write_request,
+      METH_VARARGS,
+      "Returns TRUE if there is space to write a request message.\n" },
+
+    { "response_to_read",
+      (PyCFunction)xu_port_response_to_read,
+      METH_VARARGS,
+      "Returns TRUE if there is a response message to read.\n" },
+
+    { "space_to_write_response",
+      (PyCFunction)xu_port_space_to_write_response,
+      METH_VARARGS,
+      "Returns TRUE if there is space to write a response message.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_port_type;
+
+static PyObject *xu_port_new(PyObject *self, PyObject *args)
+{
+    xu_port_object *xup;
+    u32 dom;
+    int port1, port2;
+    xc_dominfo_t info;
+
+    if ( !PyArg_ParseTuple(args, "i", &dom) )
+        return NULL;
+
+    xup = PyObject_New(xu_port_object, &xu_port_type);
+
+    if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 )
+    {
+        PyErr_SetString(port_error, "Could not open '/dev/mem'");
+        goto fail1;
+    }
+
+    /* Set the General-Purpose Subject whose page frame will be mapped. */
+    (void)ioctl(xup->mem_fd, _IO('M', 1), (unsigned long)dom);
+
+    if ( (xup->xc_handle = xc_interface_open()) == -1 )
+    {
+        PyErr_SetString(port_error, "Could not open Xen control interface");
+        goto fail2;
+    }
+
+    if ( dom == 0 )
+    {
+        /*
+         * The control-interface event channel for DOM0 is already set up.
+         * We use an ioctl to discover the port at our end of the channel.
+         */
+        port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
+        port2 = -1; /* We don't need the remote end of the DOM0 link. */
+        if ( port1 < 0 )
+        {
+            PyErr_SetString(port_error, "Could not open channel to DOM0");
+            goto fail3;
+        }
+    }
+    else if ( xc_evtchn_bind_interdomain(xup->xc_handle, 
+                                         DOMID_SELF, dom, 
+                                         &port1, &port2) != 0 )
+    {
+        PyErr_SetString(port_error, "Could not open channel to domain");
+        goto fail3;
+    }
+
+    if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) ||
+         (info.domid != dom) )
+    {
+        PyErr_SetString(port_error, "Failed to obtain domain status");
+        goto fail4;
+    }
+
+    xup->interface = 
+        map_control_interface(xup->mem_fd, info.shared_info_frame);
+    if ( xup->interface == NULL )
+    {
+        PyErr_SetString(port_error, "Failed to map domain control interface");
+        goto fail4;
+    }
+
+    xup_connect(xup, dom, port1, port2);
+    return (PyObject *)xup;
+
+    
+ fail4:
+    (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
+ fail3:
+    (void)xc_interface_close(xup->xc_handle);
+ fail2:
+    (void)close(xup->mem_fd);
+ fail1:
+    PyObject_Del((PyObject *)xup);
+    return NULL;        
+}
+
+static PyObject *xu_port_getattr(PyObject *obj, char *name)
+{
+    xu_port_object *xup = (xu_port_object *)obj;
+    if ( strcmp(name, "local_port") == 0 )
+        return PyInt_FromLong(xup->local_port);
+    if ( strcmp(name, "remote_port") == 0 )
+        return PyInt_FromLong(xup->remote_port);
+    if ( strcmp(name, "remote_dom") == 0 )
+        return PyInt_FromLong(xup->remote_dom);
+    return Py_FindMethod(xu_port_methods, obj, name);
+}
+
+static void xu_port_dealloc(PyObject *self)
+{
+    xu_port_object *xup = (xu_port_object *)self;
+    unmap_control_interface(xup->mem_fd, xup->interface);
+    if ( xup->remote_dom != 0 )
+        (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
+    (void)xc_interface_close(xup->xc_handle);
+    (void)close(xup->mem_fd);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_port_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "port",
+    sizeof(xu_port_object),
+    0,
+    xu_port_dealloc,     /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_port_getattr,     /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** BUFFER ***********************
+ */
+
+#define BUFSZ 65536
+#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
+typedef unsigned int BUF_IDX;
+
+typedef struct {
+    PyObject_HEAD;
+    char        *buf;
+    unsigned int prod, cons;
+} xu_buffer_object;
+
+static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
+{
+    PyObject *str1, *str2;
+    int len1, len2, c = MASK_BUF_IDX(xub->cons);
+
+    len1 = xub->prod - xub->cons;
+    if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
+        len1 = BUFSZ - c;
+    if ( len1 > max )         /* clip to specified maximum */
+        len1 = max;
+    if ( len1 < 0 )           /* sanity */
+        len1 = 0;
+
+    if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
+        return NULL;
+
+    if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
+    {
+        len2 = max - len1;
+        if ( len2 > MASK_BUF_IDX(xub->prod) )
+            len2 = MASK_BUF_IDX(xub->prod);
+        if ( len2 > 0 )
+        {
+            str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
+            if ( str2 == NULL )
+                return NULL;
+            PyString_ConcatAndDel(&str1, str2);
+            if ( str1 == NULL )
+                return NULL;
+        }
+    }
+
+    return str1;
+}
+
+static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    int max = 1024;
+
+    if ( !PyArg_ParseTuple(args, "|i", &max) )
+        return NULL;
+    
+    return __xu_buffer_peek(xub, max);
+}
+
+static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    PyObject *str;
+    int max = 1024;
+
+    if ( !PyArg_ParseTuple(args, "|i", &max) )
+        return NULL;
+
+    if ( (str = __xu_buffer_peek(xub, max)) != NULL )
+        xub->cons += PyString_Size(str);
+
+    return str;
+}
+
+static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    int max, len;
+
+    if ( !PyArg_ParseTuple(args, "i", &max) )
+        return NULL;
+
+    len = xub->prod - xub->cons;
+    if ( len > max )
+        len = max;
+    if ( len < 0 )
+        len = 0;
+
+    xub->cons += len;
+
+    return PyInt_FromLong(len);
+}
+
+static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    char *str;
+    int len, len1, len2;
+
+    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+        return NULL;
+
+    len1 = len;
+    if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+        len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
+    if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
+        len1 = BUFSZ - (xub->prod - xub->cons);
+
+    if ( len1 == 0 )
+        return PyInt_FromLong(0);
+
+    memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
+    xub->prod += len1;
+
+    if ( len1 < len )
+    {
+        len2 = len - len1;
+        if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+            len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
+        if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
+            len2 = BUFSZ - (xub->prod - xub->cons);
+        if ( len2 != 0 )
+        {
+            memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
+            xub->prod += len2;
+            return PyInt_FromLong(len1 + len2);
+        }
+    }
+
+    return PyInt_FromLong(len1);
+}
+
+static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( xub->cons == xub->prod )
+        return PyInt_FromLong(1);
+
+    return PyInt_FromLong(0);
+}
+
+static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (xub->prod - xub->cons) == BUFSZ )
+        return PyInt_FromLong(1);
+
+    return PyInt_FromLong(0);
+}
+
+static PyMethodDef xu_buffer_methods[] = {
+    { "peek", 
+      (PyCFunction)xu_buffer_peek,
+      METH_VARARGS,
+      "Peek up to @max bytes from the buffer. Returns a string.\n" },
+
+    { "read", 
+      (PyCFunction)xu_buffer_read,
+      METH_VARARGS,
+      "Read up to @max bytes from the buffer. Returns a string.\n" },
+
+    { "discard", 
+      (PyCFunction)xu_buffer_discard,
+      METH_VARARGS,
+      "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
+
+    { "write", 
+      (PyCFunction)xu_buffer_write,
+      METH_VARARGS,
+      "Write @string into buffer. Return number of bytes written.\n" },
+
+    { "empty", 
+      (PyCFunction)xu_buffer_empty,
+      METH_VARARGS,
+      "Return TRUE if the buffer is empty.\n" },
+
+    { "full", 
+      (PyCFunction)xu_buffer_full,
+      METH_VARARGS,
+      "Return TRUE if the buffer is full.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_buffer_type;
+
+static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
+
+    if ( (xub->buf = malloc(BUFSZ)) == NULL )
+    {
+        PyObject_Del((PyObject *)xub);
+        return NULL;
+    }
+
+    xub->prod = xub->cons = 0;
+
+    return (PyObject *)xub;
+}
+
+static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
+{
+    return Py_FindMethod(xu_buffer_methods, obj, name);
+}
+
+static void xu_buffer_dealloc(PyObject *self)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    free(xub->buf);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_buffer_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "buffer",
+    sizeof(xu_buffer_object),
+    0,
+    xu_buffer_dealloc,   /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_buffer_getattr,   /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** MODULE WRAPPER ***********************
+ */
+
+static void handle_child_death(int dummy)
+{
+    while ( waitpid(-1, NULL, WNOHANG) > 0 )
+        continue;
+}
+
+static PyObject *xu_autoreap(PyObject *self, PyObject *args)
+{
+    struct sigaction sa;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = handle_child_death;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+    (void)sigaction(SIGCHLD, &sa, NULL);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMethodDef xu_methods[] = {
+    { "notifier", xu_notifier_new, METH_VARARGS, 
+      "Create a new notifier." },
+    { "message", xu_message_new, METH_VARARGS, 
+      "Create a new communications message." },
+    { "port", xu_port_new, METH_VARARGS, 
+      "Create a new communications port." },
+    { "buffer", xu_buffer_new, METH_VARARGS, 
+      "Create a new ring buffer." },
+    { "autoreap", xu_autoreap, METH_VARARGS,
+      "Ensure that zombie children are automatically reaped by the OS." },
+    { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC initutils(void)
+{
+    PyObject *m, *d;
+
+    m = Py_InitModule("xend.utils", xu_methods);
+
+    d = PyModule_GetDict(m);
+    port_error = PyErr_NewException("xend.utils.PortError", NULL, NULL);
+    PyDict_SetItemString(d, "PortError", port_error);
+}
diff --git a/tools/xend-old/setup.py b/tools/xend-old/setup.py
new file mode 100644 (file)
index 0000000..66ed7a9
--- /dev/null
@@ -0,0 +1,19 @@
+
+from distutils.core import setup, Extension
+
+utils = Extension("utils",
+                  extra_compile_args   = ["-fno-strict-aliasing"],
+                  include_dirs         = ["../xc/lib",
+                                          "../../xen/include/hypervisor-ifs",
+                                          "../../linux-xen-sparse/include"],
+                  library_dirs         = ["../xc/lib"],
+                  libraries            = ["xc"],
+                  sources              = ["lib/utils.c"])
+
+setup(name = "xend",
+      version = "1.0",
+      packages = ["xend"],
+      package_dir = { "xend" : "lib" },
+      ext_package = "xend",
+      ext_modules = [ utils ]
+      )
diff --git a/tools/xend-old/xend b/tools/xend-old/xend
new file mode 100755 (executable)
index 0000000..6e321bb
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+import os, sys, xend.main
+
+def main():
+    if not sys.argv[1:]:
+        print 'usage: %s {start|stop|restart}' % sys.argv[0]
+    elif os.fork():
+        pid, status = os.wait()
+        return status >> 8
+    elif sys.argv[1] == 'start':
+        return xend.main.start_daemon()
+    elif sys.argv[1] == 'stop':
+        return xend.main.stop_daemon()
+    elif sys.argv[1] == 'restart':
+        return xend.main.stop_daemon() or xend.main.start_daemon()
+    else:
+        print 'not an option:', sys.argv[1]
+    return 1
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/tools/xend/Makefile b/tools/xend/Makefile
deleted file mode 100644 (file)
index 8e28c03..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-
-all:
-       python setup.py build
-
-install: all
-       if [ "$(prefix)" = "" ]; then                   \
-           python setup.py install;                    \
-       elif [ "$(dist)" = "yes" ]; then                \
-           python setup.py install --home="$(prefix)"; \
-       else                                            \
-           python setup.py install --root="$(prefix)"; \
-       fi
-       mkdir -p $(prefix)/usr/sbin
-       install -m0755 xend $(prefix)/usr/sbin
-
-clean:
-       rm -rf build *.pyc *.pyo *.a *.so *.o *~ *.rpm 
diff --git a/tools/xend/lib/__init__.py b/tools/xend/lib/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/tools/xend/lib/blkif.py b/tools/xend/lib/blkif.py
deleted file mode 100644 (file)
index 51431b6..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-
-#################################################################
-## xend/blkif.py -- Block-interface management functions for Xend
-## Copyright (c) 2004, K A Fraser (University of Cambridge)
-#################################################################
-
-import errno, re, os, select, signal, socket, sys
-import xend.main, xend.console, xend.manager, xend.utils, Xc
-
-CMSG_BLKIF_BE = 1
-CMSG_BLKIF_FE = 2
-CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
-CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
-CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED    = 32
-CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
-CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
-CMSG_BLKIF_BE_CREATE      = 0
-CMSG_BLKIF_BE_DESTROY     = 1
-CMSG_BLKIF_BE_CONNECT     = 2
-CMSG_BLKIF_BE_DISCONNECT  = 3
-CMSG_BLKIF_BE_VBD_CREATE  = 4
-CMSG_BLKIF_BE_VBD_DESTROY = 5
-CMSG_BLKIF_BE_VBD_GROW    = 6
-CMSG_BLKIF_BE_VBD_SHRINK  = 7
-
-BLKIF_DRIVER_STATUS_DOWN  = 0
-BLKIF_DRIVER_STATUS_UP    = 1
-
-pendmsg = None
-pendaddr = None
-
-recovery = False # Is a recovery in progress? (if so we'll need to notify guests)
-be_port  = None  # Port object for backend domain
-
-def backend_tx_req(msg):
-    port = xend.blkif.be_port
-    if not port:
-        print "BUG: attempt to transmit request to non-existant blkif driver"
-    if port.space_to_write_request():
-        port.write_request(msg)
-        port.notify()
-    else:
-        xend.blkif.pendmsg = msg
-
-def backend_rx_req(port, msg):
-    port.write_response(msg)
-    subtype = (msg.get_header())['subtype']
-    print "Received blkif-be request, subtype %d" % subtype
-    if subtype == CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
-        status = (msg.get_payload())['status']
-        if status == BLKIF_DRIVER_STATUS_UP:
-            if xend.blkif.recovery:
-                # Nasty hack: we count the number of VBDs we reattach so that
-                # we'll know when to notify the guests.  Must make this better!
-                interface.rebuilt_so_far = 0
-                interface.nr_to_rebuild  = 0
-                print "New blkif backend now UP, rebuilding VBDs:"
-                for blkif_key in interface.list.keys():
-                    blkif = interface.list[blkif_key]
-                    blkif.create()
-                    for vdev in blkif.devices.keys():
-                        blkif.reattach_device(vdev)
-                        interface.nr_to_rebuild += 1
-        else:
-            print "Unexpected block backend driver status: %d" % status
-
-
-def backend_rx_rsp(port, msg):
-    subtype = (msg.get_header())['subtype']
-    print "Received blkif-be response, subtype %d" % subtype
-    if subtype == CMSG_BLKIF_BE_CREATE:
-        rsp = { 'success': True }
-        xend.main.send_management_response(rsp, xend.blkif.pendaddr)
-    elif subtype == CMSG_BLKIF_BE_CONNECT:
-        pl = msg.get_payload()
-        (dom, hnd, frame, evtchn, st) = (pl['domid'], pl['blkif_handle'],
-                                         pl['shmem_frame'], pl['evtchn'],
-                                         pl['status'])
-        blkif = interface.list[xend.main.port_from_dom(dom).local_port]
-        msg = xend.utils.message(CMSG_BLKIF_FE,
-                                 CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED, 0,
-                                 { 'handle' : 0, 'status' : 2,
-                                   'evtchn' : blkif.evtchn['port2'] })
-        blkif.ctrlif_tx_req(xend.main.port_list[blkif.key], msg)
-    elif subtype == CMSG_BLKIF_BE_VBD_CREATE:
-        pl = msg.get_payload()
-        (dom, hnd, vdev, ro, st) = (pl['domid'], pl['blkif_handle'],
-                                    pl['vdevice'], pl['readonly'],
-                                    pl['status'])
-        blkif = interface.list[xend.main.port_from_dom(dom).local_port]
-        (pdev, start_sect, nr_sect, readonly) = blkif.devices[vdev]
-        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW, 0,
-                                 { 'domid' : dom, 'blkif_handle' : 0,
-                                   'vdevice' : vdev,
-                                   'extent.sector_start' : start_sect,
-                                   'extent.sector_length' : nr_sect,
-                                   'extent.device' : pdev })
-        backend_tx_req(msg)
-    elif subtype == CMSG_BLKIF_BE_VBD_GROW:
-       if not xend.blkif.recovery:
-           rsp = { 'success': True }
-           xend.main.send_management_response(rsp, xend.blkif.pendaddr)
-       else:
-           interface.rebuilt_so_far += 1
-           if interface.rebuilt_so_far == interface.nr_to_rebuild:
-               print "Rebuilt VBDs, notifying guests:"
-               for blkif_key in interface.list.keys():
-                   blkif = interface.list[blkif_key]
-                   print "  Notifying %d" % blkif.dom
-                   msg = xend.utils.message(CMSG_BLKIF_FE,
-                                            CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED,
-                                            0, { 'handle' : 0, 'status' : 1 })
-                   blkif.ctrlif_tx_req(xend.main.port_from_dom(blkif.dom),msg)
-               xend.blkif.recovery = False
-               print "Done notifying guests"
-
-
-def backend_do_work(port):
-    global pendmsg
-    if pendmsg and port.space_to_write_request():
-        port.write_request(pendmsg)
-        pendmsg = None
-        return True
-    return False
-
-
-class interface:
-
-    # Dictionary of all block-device interfaces.
-    list = {}
-
-    # NB. 'key' is an opaque value that has no meaning in this class.
-    def __init__(self, dom, key):
-        self.dom     = dom
-        self.key     = key
-        self.devices = {}
-        self.pendmsg = None
-        interface.list[key] = self
-        self.create()
-
-    def create(self):
-        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE, 0,
-                                 { 'domid' : self.dom, 'blkif_handle' : 0 })
-        xend.blkif.pendaddr = xend.main.mgmt_req_addr
-        backend_tx_req(msg)
-
-    # Attach a device to the specified interface
-    def attach_device(self, vdev, pdev, start_sect, nr_sect, readonly):
-        if self.devices.has_key(vdev):
-            return False
-        self.devices[vdev] = (pdev, start_sect, nr_sect, readonly)
-        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE, 0,
-                                 { 'domid' : self.dom, 'blkif_handle' : 0,
-                                   'vdevice' : vdev, 'readonly' : readonly })
-        xend.blkif.pendaddr = xend.main.mgmt_req_addr
-        backend_tx_req(msg)
-        return True
-
-    def reattach_device(self, vdev):
-        (pdev, start_sect, nr_sect, readonly) = self.devices[vdev]
-        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE,
-                                 0, { 'domid' : self.dom,
-                                      'blkif_handle' : 0,
-                                      'vdevice' : vdev,
-                                      'readonly' : readonly })
-        xend.blkif.pendaddr = xend.main.mgmt_req_addr
-        backend_tx_req(msg)
-
-    # Completely destroy this interface.
-    def destroy(self):
-        del interface.list[self.key]
-        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY, 0,
-                                 { 'domid' : self.dom, 'blkif_handle' : 0 })
-        backend_tx_req(msg)        
-
-
-    # The parameter @port is the control-interface event channel. This method
-    # returns True if messages were written to the control interface.
-    def ctrlif_transmit_work(self, port):
-        if self.pendmsg and port.space_to_write_request():
-            port.write_request(self.pendmsg)
-            self.pendmsg = None
-            return True
-        return False
-
-    def ctrlif_tx_req(self, port, msg):
-        if port.space_to_write_request():
-            port.write_request(msg)
-            port.notify()
-        else:
-            self.pendmsg = msg
-
-    def ctrlif_rx_req(self, port, msg):
-        port.write_response(msg)
-        subtype = (msg.get_header())['subtype']
-        if subtype == CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
-            msg = xend.utils.message(CMSG_BLKIF_FE,
-                                     CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED,
-                                     0,
-                                     { 'handle' : 0, 'status' : 1 })
-            self.ctrlif_tx_req(port, msg)
-        elif subtype == CMSG_BLKIF_FE_INTERFACE_CONNECT:
-            pl = msg.get_payload()
-            (hnd, frame) = (pl['handle'], pl['shmem_frame'])
-            xc = Xc.new()
-            self.evtchn = xc.evtchn_bind_interdomain(
-                                            dom1=xend.blkif.be_port.remote_dom,
-                                            dom2=self.dom)
-            msg = xend.utils.message(CMSG_BLKIF_BE,
-                                     CMSG_BLKIF_BE_CONNECT, 0,
-                                     { 'domid' : self.dom, 'blkif_handle' : 0,
-                                       'shmem_frame' : frame,
-                                       'evtchn' : self.evtchn['port1'] })
-            backend_tx_req(msg)
diff --git a/tools/xend/lib/console.py b/tools/xend/lib/console.py
deleted file mode 100644 (file)
index 5789881..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-
-#############################################################
-## xend/console.py -- Console-management functions for Xend
-## Copyright (c) 2004, K A Fraser (University of Cambridge)
-#############################################################
-
-import errno, re, os, select, signal, socket, struct, sys
-import xend.blkif, xend.main, xend.manager, xend.utils, Xc
-
-##
-## interface:
-##  Each control interface owns an instance of this class, which manages
-##  the current state of the console interface. Normally a console interface
-##  will be one of two state:
-##   LISTENING: listening for a connection on TCP port 'self.port'
-##   CONNECTED: sending/receiving console data on TCP port 'self.port'
-##
-##  A dictionary of all active interfaces, indexed by TCP socket descriptor,
-##  is accessible as 'interface.list_by_fd'.
-##
-##  NB. When a class instance is to be destroyed you *must* call the 'close'
-##  method. Otherwise a stale reference will eb left in the interface list.
-##
-class interface:
-
-    # The various states that a console interface may be in.
-    CLOSED    = 0 # No console activity
-    LISTENING = 1 # Listening on port 'self.port'. Socket object 'self.sock'.
-    CONNECTED = 2 # Active connection on 'self.port'. Socket obj 'self.sock'.
-
-
-    # Dictionary of all active (non-closed) console interfaces.
-    list_by_fd = {}
-
-
-    # Dictionary of all console interfaces, closed and open.
-    list = {}
-
-
-    # NB. 'key' is an opaque value that has no meaning in this class.
-    def __init__(self, port, key):
-        self.status = interface.CLOSED
-        self.port   = port
-        self.key    = key
-        self.rbuf   = xend.utils.buffer()
-        self.wbuf   = xend.utils.buffer()
-        interface.list[key] = self
-
-
-    # Is this interface closed (inactive)?
-    def closed(self):
-        return self.status == interface.CLOSED
-
-
-    # Is this interface listening?
-    def listening(self):
-        return self.status == interface.LISTENING
-
-
-    # Is this interface active and connected?
-    def connected(self):
-        return self.status == interface.CONNECTED
-
-
-    # Close the interface, if it is not closed already.
-    def close(self):
-        if not self.closed():
-            del interface.list_by_fd[self.sock.fileno()]
-            self.sock.close()
-            del self.sock
-            self.status = interface.CLOSED
-
-
-    # Move the interface into the 'listening' state. Opens a new listening
-    # socket and updates 'list_by_fd'.
-    def listen(self):
-        # Close old socket (if any), and create a fresh one.
-        self.close()
-        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
-
-        try:
-            # Turn the new socket into a non-blocking listener.
-            self.sock.setblocking(False)
-            self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-            self.sock.bind(('', self.port))
-            self.sock.listen(1)
-
-            # Announce the new status of thsi interface.
-            self.status = interface.LISTENING
-            interface.list_by_fd[self.sock.fileno()] = self
-
-        except:
-            # In case of trouble ensure we get rid of dangling socket reference
-            self.sock.close()
-            del self.sock
-            raise
-
-
-    # Move a listening interface into the 'connected' state.
-    def connect(self):
-        # Pick up a new connection, if one is available.
-        try:
-            (sock, addr) = self.sock.accept()
-        except:
-            return 0
-        sock.setblocking(False)
-        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-
-        # Close the listening socket.
-        self.sock.close()
-
-        # Publish the new socket and the new interface state.
-        self.sock = sock
-        self.status = interface.CONNECTED
-        interface.list_by_fd[self.sock.fileno()] = self
-        return 1
-
-
-    # Completely sestroy a console interface.
-    def destroy(self):
-        self.close()
-        del interface.list[self.key]
-
-
-    # Do work triggered by resource availability on a console-interface socket.
-    def socket_work(self):
-        # If the interface is listening, check for pending connections.
-        if self.listening():
-            self.connect()
-
-        # All done if the interface is not connected.
-        if not self.connected():
-            return
-
-        # Send as much pending data as possible via the socket.
-        while not self.rbuf.empty():
-            try:
-                bytes = self.sock.send(self.rbuf.peek())
-                if bytes > 0:
-                    self.rbuf.discard(bytes)
-            except socket.error, error:
-                pass
-
-        # Read as much data as is available. Don't worry about
-        # overflowing our buffer: it's more important to read the
-        # incoming data stream and detect errors or closure of the
-        # remote end in a timely manner.
-        try:
-            while 1:
-                data = self.sock.recv(2048)
-                # Return of zero means the remote end has disconnected.
-                # We therefore return the console interface to listening.
-                if not data:
-                    self.listen()
-                    break
-                self.wbuf.write(data)
-        except socket.error, error:
-            # Assume that most errors mean that the connection is dead.
-            # In such cases we return the interface to 'listening' state.
-            if error[0] != errno.EAGAIN:
-                print "Better return to listening"
-                self.listen()
-                print "New status: " + str(self.status)
-
-
-    # The parameter @port is the control-interface event channel. This method
-    # returns True if messages were written to the control interface.
-    def ctrlif_transmit_work(self, port):
-        work_done = False
-        while not self.wbuf.empty() and port.space_to_write_request():
-            msg = xend.utils.message(0, 0, 0)
-            msg.append_payload(self.wbuf.read(msg.MAX_PAYLOAD))
-            port.write_request(msg)
-            work_done = True
-        return work_done
-
-
-    def ctrlif_rx_req(self, port, msg):
-        self.rbuf.write(msg.get_payload())
-        port.write_response(msg)
diff --git a/tools/xend/lib/domain_controller.h b/tools/xend/lib/domain_controller.h
deleted file mode 100644 (file)
index 76dd164..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-/******************************************************************************
- * domain_controller.h
- * 
- * Interface to server controller (e.g., 'xend'). This header file defines the 
- * interface that is shared with guest OSes.
- * 
- * Copyright (c) 2004, K A Fraser
- */
-
-#ifndef __DOMAIN_CONTROLLER_H__
-#define __DOMAIN_CONTROLLER_H__
-
-
-#ifndef BASIC_START_INFO
-#error "Xen header file hypervisor-if.h must already be included here."
-#endif
-
-
-/*
- * EXTENDED BOOTSTRAP STRUCTURE FOR NEW DOMAINS.
- */
-
-typedef struct {
-    BASIC_START_INFO;
-    u16 domain_controller_evtchn; /* 320 */
-} PACKED extended_start_info_t; /* 322 bytes */
-#define SIF_BLK_BE_DOMAIN (1<<4)  /* Is this a block backend domain? */
-#define SIF_NET_BE_DOMAIN (1<<5)  /* Is this a net backend domain? */
-
-
-/*
- * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
- * interpreted by control software to determine the appropriate action. These 
- * are only really advisories: the controller can actually do as it likes.
- */
-#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
-#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
-#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
-
-
-/*
- * CONTROLLER MESSAGING INTERFACE.
- */
-
-typedef struct {
-    u8 type;     /*  0: echoed in response */
-    u8 subtype;  /*  1: echoed in response */
-    u8 id;       /*  2: echoed in response */
-    u8 length;   /*  3: number of bytes in 'msg' */
-    u8 msg[60];  /*  4: type-specific message data */
-} PACKED control_msg_t; /* 64 bytes */
-
-#define CONTROL_RING_SIZE 8
-typedef u32 CONTROL_RING_IDX;
-#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
-
-typedef struct {
-    control_msg_t tx_ring[CONTROL_RING_SIZE];   /*    0: guest -> controller */
-    control_msg_t rx_ring[CONTROL_RING_SIZE];   /*  512: controller -> guest */
-    CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
-    CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
-} PACKED control_if_t; /* 1040 bytes */
-
-/*
- * Top-level command types.
- */
-#define CMSG_CONSOLE        0  /* Console                 */
-#define CMSG_BLKIF_BE       1  /* Block-device backend    */
-#define CMSG_BLKIF_FE       2  /* Block-device frontend   */
-#define CMSG_NETIF_BE       3  /* Network-device backend  */
-#define CMSG_NETIF_FE       4  /* Network-device frontend */
-#define CMSG_SHUTDOWN       6  /* Shutdown messages       */
-
-
-/******************************************************************************
- * CONSOLE DEFINITIONS
- */
-
-/*
- * Subtypes for console messages.
- */
-#define CMSG_CONSOLE_DATA       0
-
-
-/******************************************************************************
- * BLOCK-INTERFACE FRONTEND DEFINITIONS
- */
-
-/* Messages from domain controller to guest. */
-#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED   0
-
-/* Messages from guest to domain controller. */
-#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
-#define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
-#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
-
-/* These are used by both front-end and back-end drivers. */
-#define blkif_vdev_t   u16
-#define blkif_pdev_t   u16
-#define blkif_sector_t u64
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
- *  Notify a guest about a status change on one of its block interfaces.
- *  If the interface is DESTROYED or DOWN then the interface is disconnected:
- *   1. The shared-memory frame is available for reuse.
- *   2. Any unacknowledged messgaes pending on the interface were dropped.
- */
-#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
-#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
-#define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
-typedef struct {
-    u32 handle; /*  0 */
-    u32 status; /*  4 */
-    u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
-} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
-
-/*
- * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the front-end driver is DOWN or UP.
- *  When the driver goes DOWN then the controller will send no more
- *  status-change notifications. When the driver comes UP then the controller
- *  will send a notification for each interface that currently exists.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically take the interfaces DOWN.
- */
-#define BLKIF_DRIVER_STATUS_DOWN   0
-#define BLKIF_DRIVER_STATUS_UP     1
-typedef struct {
-    /* IN */
-    u32 status;        /*  0: BLKIF_DRIVER_STATUS_??? */
-    /* OUT */
-    /*
-     * Tells driver how many interfaces it should expect to immediately
-     * receive notifications about.
-     */
-    u32 nr_interfaces; /*  4 */
-} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_CONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_CONNECTED message.
- */
-typedef struct {
-    u32      handle;      /*  0 */
-    u32      __pad;
-    memory_t shmem_frame; /*  8 */
-    MEMORY_PADDING;
-} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_DISCONNECTED message.
- */
-typedef struct {
-    u32 handle; /*  0 */
-} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
-
-
-/******************************************************************************
- * BLOCK-INTERFACE BACKEND DEFINITIONS
- */
-
-/* Messages from domain controller. */
-#define CMSG_BLKIF_BE_CREATE      0  /* Create a new block-device interface. */
-#define CMSG_BLKIF_BE_DESTROY     1  /* Destroy a block-device interface.    */
-#define CMSG_BLKIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
-#define CMSG_BLKIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
-#define CMSG_BLKIF_BE_VBD_CREATE  4  /* Create a new VBD for an interface.   */
-#define CMSG_BLKIF_BE_VBD_DESTROY 5  /* Delete a VBD from an interface.      */
-#define CMSG_BLKIF_BE_VBD_GROW    6  /* Append an extent to a given VBD.     */
-#define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
-
-/* Messages to domain controller. */
-#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
-
-/*
- * Message request/response definitions for block-device messages.
- */
-
-typedef struct {
-    blkif_sector_t sector_start;   /*  0 */
-    blkif_sector_t sector_length;  /*  8 */
-    blkif_pdev_t   device;         /* 16 */
-    u16            __pad;          /* 18 */
-} PACKED blkif_extent_t; /* 20 bytes */
-
-/* Non-specific 'okay' return. */
-#define BLKIF_BE_STATUS_OKAY                0
-/* Non-specific 'error' return. */
-#define BLKIF_BE_STATUS_ERROR               1
-/* The following are specific error returns. */
-#define BLKIF_BE_STATUS_INTERFACE_EXISTS    2
-#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
-#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
-#define BLKIF_BE_STATUS_VBD_EXISTS          5
-#define BLKIF_BE_STATUS_VBD_NOT_FOUND       6
-#define BLKIF_BE_STATUS_OUT_OF_MEMORY       7
-#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    8
-#define BLKIF_BE_STATUS_MAPPING_ERROR       9
-
-/* This macro can be used to create an array of descriptive error strings. */
-#define BLKIF_BE_STATUS_ERRORS {    \
-    "Okay",                         \
-    "Non-specific error",           \
-    "Interface already exists",     \
-    "Interface not found",          \
-    "Interface is still connected", \
-    "VBD already exists",           \
-    "VBD not found",                \
-    "Out of memory",                \
-    "Extent not found for VBD",     \
-    "Could not map domain memory" }
-
-/*
- * CMSG_BLKIF_BE_CREATE:
- *  When the driver sends a successful response then the interface is fully
- *  created. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_create_t; /* 12 bytes */
-
-/*
- * CMSG_BLKIF_BE_DESTROY:
- *  When the driver sends a successful response then the interface is fully
- *  torn down. The controller will send a DESTROYED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify interface to be destroyed. */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_destroy_t; /* 12 bytes */
-
-/*
- * CMSG_BLKIF_BE_CONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  connected. The controller will send a CONNECTED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    memory_t   shmem_frame;   /*  8: Page cont. shared comms window.     */
-    MEMORY_PADDING;
-    u32        evtchn;        /* 16: Event channel for notifications.    */
-    /* OUT */
-    u32        status;        /* 20 */
-} PACKED blkif_be_connect_t;  /* 24 bytes */
-
-/*
- * CMSG_BLKIF_BE_DISCONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  disconnected. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_disconnect_t; /* 12 bytes */
-
-/* CMSG_BLKIF_BE_VBD_CREATE */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id for this VBD. */
-    u16        readonly;      /* 10: Non-zero -> VBD isn't writeable.    */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_create_t; /* 16 bytes */
-
-/* CMSG_BLKIF_BE_VBD_DESTROY */
-typedef struct {
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
-    u16        __pad;         /* 10 */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
-
-/* CMSG_BLKIF_BE_VBD_GROW */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_extent_t extent;    /*  8: Physical extent to append to VBD.   */
-    blkif_vdev_t vdevice;     /* 28: Interface-specific id of the VBD.   */
-    u16        __pad;         /* 30 */
-    /* OUT */
-    u32        status;        /* 32 */
-} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
-
-/* CMSG_BLKIF_BE_VBD_SHRINK */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
-    u16        __pad;         /* 10 */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
-
-/*
- * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the back-end driver is DOWN or UP.
- *  If the driver goes DOWN while interfaces are still UP, the controller
- *  will automatically send DOWN notifications.
- */
-typedef struct {
-    u32        status;        /*  0: BLKIF_DRIVER_STATUS_??? */
-} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
-
-
-/******************************************************************************
- * NETWORK-INTERFACE FRONTEND DEFINITIONS
- */
-
-/* Messages from domain controller to guest. */
-#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
-
-/* Messages from guest to domain controller. */
-#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
-#define CMSG_NETIF_FE_INTERFACE_CONNECT         33
-#define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
-
-/*
- * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
- *  Notify a guest about a status change on one of its network interfaces.
- *  If the interface is DESTROYED or DOWN then the interface is disconnected:
- *   1. The shared-memory frame is available for reuse.
- *   2. Any unacknowledged messgaes pending on the interface were dropped.
- */
-#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
-#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
-#define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
-typedef struct {
-    u32        handle; /*  0 */
-    u32        status; /*  4 */
-    u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
-    u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
-} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
-
-/*
- * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the front-end driver is DOWN or UP.
- *  When the driver goes DOWN then the controller will send no more
- *  status-change notifications. When the driver comes UP then the controller
- *  will send a notification for each interface that currently exists.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically take the interfaces DOWN.
- */
-#define NETIF_DRIVER_STATUS_DOWN   0
-#define NETIF_DRIVER_STATUS_UP     1
-typedef struct {
-    /* IN */
-    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
-    /* OUT */
-    /*
-     * Tells driver how many interfaces it should expect to immediately
-     * receive notifications about.
-     */
-    u32        nr_interfaces; /*  4 */
-} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
-
-/*
- * CMSG_NETIF_FE_INTERFACE_CONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_CONNECTED message.
- */
-typedef struct {
-    u32        handle;         /*  0 */
-    u32        __pad;          /*  4 */
-    memory_t   tx_shmem_frame; /*  8 */
-    MEMORY_PADDING;
-    memory_t   rx_shmem_frame; /* 16 */
-    MEMORY_PADDING;
-} PACKED netif_fe_interface_connect_t; /* 24 bytes */
-
-/*
- * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_DISCONNECTED message.
- */
-typedef struct {
-    u32        handle;        /*  0 */
-} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
-
-
-/******************************************************************************
- * NETWORK-INTERFACE BACKEND DEFINITIONS
- */
-
-/* Messages from domain controller. */
-#define CMSG_NETIF_BE_CREATE      0  /* Create a new net-device interface. */
-#define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
-#define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
-#define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
-
-/* Messages to domain controller. */
-#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
-
-/*
- * Message request/response definitions for net-device messages.
- */
-
-/* Non-specific 'okay' return. */
-#define NETIF_BE_STATUS_OKAY                0
-/* Non-specific 'error' return. */
-#define NETIF_BE_STATUS_ERROR               1
-/* The following are specific error returns. */
-#define NETIF_BE_STATUS_INTERFACE_EXISTS    2
-#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
-#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
-#define NETIF_BE_STATUS_OUT_OF_MEMORY       5
-#define NETIF_BE_STATUS_MAPPING_ERROR       6
-
-/* This macro can be used to create an array of descriptive error strings. */
-#define NETIF_BE_STATUS_ERRORS {    \
-    "Okay",                         \
-    "Non-specific error",           \
-    "Interface already exists",     \
-    "Interface not found",          \
-    "Interface is still connected", \
-    "Out of memory",                \
-    "Could not map domain memory" }
-
-/*
- * CMSG_NETIF_BE_CREATE:
- *  When the driver sends a successful response then the interface is fully
- *  created. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
-    u8         mac[6];        /*  8 */
-    u16        __pad;         /* 14 */
-    /* OUT */
-    u32        status;        /* 16 */
-} PACKED netif_be_create_t; /* 20 bytes */
-
-/*
- * CMSG_NETIF_BE_DESTROY:
- *  When the driver sends a successful response then the interface is fully
- *  torn down. The controller will send a DESTROYED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify interface to be destroyed. */
-    u32        netif_handle;  /*  4: ...ditto...                         */
-    /* OUT */
-    u32   status;             /*  8 */
-} PACKED netif_be_destroy_t; /* 12 bytes */
-
-/*
- * CMSG_NETIF_BE_CONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  connected. The controller will send a CONNECTED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;          /*  0: Domain attached to new interface.   */
-    u32        netif_handle;   /*  4: Domain-specific interface handle.   */
-    memory_t   tx_shmem_frame; /*  8: Page cont. tx shared comms window.  */
-    MEMORY_PADDING;
-    memory_t   rx_shmem_frame; /* 16: Page cont. rx shared comms window.  */
-    MEMORY_PADDING;
-    u16        evtchn;         /* 24: Event channel for notifications.    */
-    u16        __pad;          /* 26 */
-    /* OUT */
-    u32        status;         /* 28 */
-} PACKED netif_be_connect_t; /* 32 bytes */
-
-/*
- * CMSG_NETIF_BE_DISCONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  disconnected. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED netif_be_disconnect_t; /* 12 bytes */
-
-/*
- * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the back-end driver is DOWN or UP.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically send DOWN notifications.
- */
-typedef struct {
-    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
-} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
-
-
-/******************************************************************************
- * SHUTDOWN DEFINITIONS
- */
-
-/*
- * Subtypes for shutdown messages.
- */
-#define CMSG_SHUTDOWN_POWEROFF  0   /* Clean shutdown (SHUTDOWN_poweroff).   */
-#define CMSG_SHUTDOWN_REBOOT    1   /* Clean shutdown (SHUTDOWN_reboot).     */
-#define CMSG_SHUTDOWN_SUSPEND   2   /* Create suspend info, then             */
-                                    /* SHUTDOWN_suspend.                     */
-
-#endif /* __DOMAIN_CONTROLLER_H__ */
diff --git a/tools/xend/lib/main.py b/tools/xend/lib/main.py
deleted file mode 100755 (executable)
index 0eecd17..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-
-###########################################################
-## xend.py -- Xen controller daemon
-## Copyright (c) 2004, K A Fraser (University of Cambridge)
-###########################################################
-
-import errno, re, os, pwd, select, signal, socket, struct, sys, time
-import xend.blkif, xend.netif, xend.console, xend.manager, xend.utils, Xc
-
-
-# The following parameters could be placed in a configuration file.
-PID  = '/var/run/xend.pid'
-LOG  = '/var/log/xend.log'
-USER = 'root'
-CONTROL_DIR  = '/var/run/xend'
-UNIX_SOCK    = 'management_sock' # relative to CONTROL_DIR
-
-
-CMSG_CONSOLE  = 0
-CMSG_BLKIF_BE = 1
-CMSG_BLKIF_FE = 2
-CMSG_NETIF_BE = 3
-CMSG_NETIF_FE = 4
-
-
-def port_from_dom(dom):
-    global port_list
-    for idx, port in port_list.items():
-        if port.remote_dom == dom:
-            return port
-    return None
-
-
-def send_management_response(response, addr):
-    try:
-        response = str(response)
-        print "Mgmt_rsp[%s]: %s" % (addr, response)
-        management_interface.sendto(response, addr)
-    except socket.error, error:
-        pass
-
-
-def daemon_loop():
-    # Could we do this more nicely? The xend.manager functions need access
-    # to this global state to do their work.
-    global port_list, notifier, management_interface, mgmt_req_addr, dom0_port
-
-    # Lists of all interfaces, indexed by local event-channel port.
-    port_list = {}
-    
-    xc = Xc.new()
-
-    # Ignore writes to disconnected sockets. We clean up differently.
-    signal.signal(signal.SIGPIPE, signal.SIG_IGN)
-
-    # Construct the management interface. This is a UNIX domain socket via
-    # which we receive 'request' datagrams. Each request is a string that
-    # can be eval'ed as a Python statement. Responses can be remotely eval'ed
-    # by the requester to create a Python dictionary of result values.
-    management_interface = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0)
-    if os.path.exists(CONTROL_DIR+'/'+UNIX_SOCK):
-        os.unlink(CONTROL_DIR+'/'+UNIX_SOCK)
-    management_interface.setblocking(False)
-    management_interface.bind(CONTROL_DIR+'/'+UNIX_SOCK)
-
-    # Interface via which we receive event notifications from other guest
-    # OSes. This interface also allows us to clear/acknowledge outstanding
-    # notifications.
-    notifier = xend.utils.notifier()
-
-    # The DOM0 control interface is not set up via the management interface.
-    # Note that console messages don't come our way (actually, only driver
-    # back-ends should use the DOM0 control interface).
-    dom0_port = xend.utils.port(0)
-    xend.netif.be_port = dom0_port
-    xend.blkif.be_port = dom0_port
-    notifier.bind(dom0_port.local_port)
-    port_list[dom0_port.local_port] = dom0_port
-
-    ##
-    ## MAIN LOOP
-    ## 
-    while 1:
-
-        # Construct a poll set. We wait on:
-        #  1. Requests on the management interface.
-        #  2. Incoming event-channel notifications.
-        # Furthermore, for each active control interface:
-        #  3. Incoming console data.
-        #  4. Space for outgoing console data (if there is data to send).
-        waitset = select.poll()
-        waitset.register(management_interface, select.POLLIN)
-        waitset.register(notifier, select.POLLIN)
-        for idx, con_if in xend.console.interface.list_by_fd.items():
-            if not con_if.closed():
-                pflags = select.POLLIN
-                if not con_if.rbuf.empty() and con_if.connected():
-                    pflags = select.POLLIN | select.POLLOUT
-                waitset.register(con_if.sock.fileno(), pflags)
-
-        # Wait for something to do...
-        fdset = waitset.poll()
-        
-        # Look for messages on the management interface.
-        # These should consist of executable Python statements that call
-        # well-known management functions (e.g., new_control_interface(dom=9)).
-        try:
-            data, mgmt_req_addr = management_interface.recvfrom(2048)
-        except socket.error, error:
-            if error[0] != errno.EAGAIN:
-                raise
-        else:
-            if mgmt_req_addr:
-                # Evaluate the request in an exception-trapping sandbox.
-                try:
-                    print "Mgmt_req[%s]: %s" % (mgmt_req_addr, data)
-                    response = eval('xend.manager.'+data)
-
-                except:
-                    # Catch all exceptions and turn into an error response:
-                    #  status:          False
-                    #  error_type:      'exception'
-                    #  exception_type:  name of exception type.
-                    #  exception value: textual exception value.
-                    exc_type, exc_val = sys.exc_info()[:2]
-                    response = { 'success': False }
-                    response['error_type'] = 'exception'
-                    response['exception_type'] = str(exc_type)
-                    response['exception_value'] = str(exc_val)
-                    response = str(response)
-
-                # Try to send a response to the requester.
-                if response:
-                    send_management_response(response, mgmt_req_addr)
-                
-        # Do work for every console interface that hit in the poll set.
-        for (fd, events) in fdset:
-            if xend.console.interface.list_by_fd.has_key(fd):
-                con_if = xend.console.interface.list_by_fd[fd]
-                con_if.socket_work()
-                # We may now have pending data to send via the control
-                # interface. If so then send all we can and notify the remote.
-                port = port_list[con_if.key]
-                if con_if.ctrlif_transmit_work(port):
-                    port.notify()
-                    
-        # Process control-interface notifications from other guest OSes.
-        while 1:            
-            # Grab a notification, if there is one.
-            notification = notifier.read()
-            if not notification:
-                break
-            (idx, type) = notification
-
-            if not port_list.has_key(idx):
-                continue
-
-            port = port_list[idx]
-            work_done = False
-
-            con_if = False
-            if xend.console.interface.list.has_key(idx):
-                con_if = xend.console.interface.list[idx]
-
-            blk_if = False
-            if xend.blkif.interface.list.has_key(idx):
-                blk_if = xend.blkif.interface.list[idx]
-
-            net_if = False
-            if xend.netif.interface.list.has_key(idx):
-                net_if = xend.netif.interface.list[idx]
-
-            # If we pick up a disconnect notification then we do any necessary
-            # cleanup.
-            if type == notifier.EXCEPTION:
-                ret = xc.evtchn_status(idx)
-                if ret['status'] == 'unbound':
-                    notifier.unbind(idx)
-                    del port_list[idx], port
-                    if con_if:
-                        con_if.destroy()
-                        del con_if
-                    if blk_if:
-                        blk_if.destroy()
-                        del blk_if
-                    if net_if:
-                        net_if.destroy()
-                        del net_if
-                    continue
-
-            # Process incoming requests.
-            while port.request_to_read():
-                msg = port.read_request()
-                work_done = True
-                type = (msg.get_header())['type']
-                if type == CMSG_CONSOLE and con_if:
-                    con_if.ctrlif_rx_req(port, msg)
-                elif type == CMSG_BLKIF_FE and blk_if:
-                    blk_if.ctrlif_rx_req(port, msg)
-                elif type == CMSG_BLKIF_BE and port == xend.blkif.be_port:
-                    xend.blkif.backend_rx_req(port, msg)
-                elif type == CMSG_NETIF_FE and net_if:
-                    net_if.ctrlif_rx_req(port, msg)
-                elif type == CMSG_NETIF_BE and port == xend.netif.be_port:
-                    xend.netif.backend_rx_req(port, msg)
-                else:
-                    port.write_response(msg)
-
-            # Process incoming responses.
-            while port.response_to_read():
-                msg = port.read_response()
-                work_done = True
-                type = (msg.get_header())['type']
-                if type == CMSG_BLKIF_BE and port == xend.blkif.be_port:
-                    xend.blkif.backend_rx_rsp(port, msg)
-                elif type == CMSG_NETIF_BE and port == xend.netif.be_port:
-                    xend.netif.backend_rx_rsp(port, msg)
-
-            # Send console data.
-            if con_if and con_if.ctrlif_transmit_work(port):
-                work_done = True
-
-            # Send blkif messages.
-            if blk_if and blk_if.ctrlif_transmit_work(port):
-                work_done = True
-
-            # Send netif messages.
-            if net_if and net_if.ctrlif_transmit_work(port):
-                work_done = True
-
-            # Back-end block-device work.
-            if port == dom0_port and xend.blkif.backend_do_work(port):
-                work_done = True
-                
-            # Back-end network-device work.
-            if port == xend.netif.be_port and xend.netif.backend_do_work(port):
-                work_done = True
-                
-            # Finally, notify the remote end of any work that we did.
-            if work_done:
-                port.notify()
-
-            # Unmask notifications for this port.
-            notifier.unmask(idx)
-
-
-
-def cleanup_daemon(kill=False):
-    # No cleanup to do if the PID file is empty.
-    if not os.path.isfile(PID) or not os.path.getsize(PID):
-        return 0
-    # Read the PID of the previous invocation and search active process list.
-    pid = open(PID, 'r').read()
-    lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
-    for line in lines:
-        if re.search('^ *' + pid + '.+xend', line):
-            if not kill:
-                print "Daemon is already running (PID %d)" % int(pid)
-                return 1
-            # Old daemon is still active: terminate it.
-            os.kill(int(pid), 1)
-    # Delete the, now stale, PID file.
-    os.remove(PID)
-    return 0
-
-
-
-def start_daemon():
-    if cleanup_daemon(kill=False):
-        return 1
-
-    if not os.path.exists(CONTROL_DIR):
-        os.mkdir(CONTROL_DIR)
-
-    # Open log file. Truncate it if non-empty, and request line buffering.
-    if os.path.isfile(LOG):
-        os.rename(LOG, LOG+'.old')
-    logfile = open(LOG, 'w+', 1)
-
-    # Detach from TTY.
-    os.setsid()
-
-    # Set the UID.
-    try:
-        os.setuid(pwd.getpwnam(USER)[2])
-    except KeyError, error:
-        print "Error: no such user '%s'" % USER
-        return 1
-
-    # Ensure that zombie children are automatically reaped.
-    xend.utils.autoreap()
-
-    # Fork -- parent writes the PID file and exits.
-    pid = os.fork()
-    if pid:
-        pidfile = open(PID, 'w')
-        pidfile.write(str(pid))
-        pidfile.close()
-        return 0
-
-    # Close down standard file handles
-    try:
-        os.close(0) # stdin
-        os.close(1) # stdout
-        os.close(2) # stderr
-    except:
-        pass
-
-    # Redirect output to log file, then enter the main loop.
-    sys.stdout = sys.stderr = logfile
-    daemon_loop()
-    return 0
-
-
-
-def stop_daemon():
-    return cleanup_daemon(kill=True)
diff --git a/tools/xend/lib/manager.py b/tools/xend/lib/manager.py
deleted file mode 100644 (file)
index 4951758..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-
-#############################################################
-## xend/manager.py -- Management-interface functions for Xend
-## Copyright (c) 2004, K A Fraser (University of Cambridge)
-#############################################################
-
-import xend.blkif, xend.netif, xend.console, xend.main, xend.utils
-
-
-##
-## new_control_interface:
-##  Create a new control interface with the specified domain @dom.
-##  The console port may also be specified; otherwise a suitable port is
-##  automatically allocated.
-##
-def new_control_interface(dom, console_port=-1):
-    # Allocate an event channel and binbd to it.
-    port = xend.utils.port(dom)
-    xend.main.notifier.bind(port.local_port)
-    
-    # If necessary, compute a suitable TCP port for console I/O.
-    if console_port < 0:
-        console_port = 9600 + port.local_port
-
-    # Create a listening console interface.
-    con_if = xend.console.interface(console_port, port.local_port)
-    con_if.listen()
-
-    # Update the master port list.
-    xend.main.port_list[port.local_port] = port
-
-    # Construct the successful response to be returned to the requester.
-    response = { 'success': True }
-    response['local_port']   = port.local_port
-    response['remote_port']  = port.remote_port
-    response['console_port'] = console_port
-    return response
-
-
-##
-## new_block_interface:
-##  Create a new block interface for the specified domain @dom.
-##
-def new_block_interface(dom, handle=-1):
-    # By default we create an interface with handle zero.
-    if handle < 0:
-        handle = 0
-
-    # We only support one interface per domain, which must have handle zero.
-    if handle != 0:
-        response = { 'success': False }
-        response['error_type'] = 'Bad handle %d (only handle 0 ' + \
-                                 'is supported)' % handle
-        return response
-
-    # Find local event-channel port associated with the specified domain.
-    port = xend.main.port_from_dom(dom)
-    if not port:
-        response = { 'success': False }
-        response['error_type'] = 'Unknown domain %d' % dom
-        return response
-
-    # The interface must not already exist.
-    if xend.blkif.interface.list.has_key(port.local_port):
-        response = { 'success': False }
-        response['error_type'] = 'Interface (dom=%d,handle=%d) already ' + \
-                                 'exists' % (dom, handle)
-        return response
-
-    # Create the new interface. Initially no virtual devices are attached.
-    xend.blkif.interface(dom, port.local_port)
-
-    # Response is deferred until back-end driver sends acknowledgement.
-    return None
-
-
-##
-## new_block_device:
-##  Attach a new virtual block device to the specified block interface
-##  (@dom, @handle). The new device is identified by @vdev, and maps to
-##  the real block extent (@pdev, @start_sect, @nr_sect). If @readonly then
-##  write requests to @vdev will be rejected.
-##
-def new_block_device(dom, handle, vdev, pdev, start_sect, nr_sect, readonly):
-    # We only support one interface per domain, which must have handle zero.
-    if handle != 0:
-        response = { 'success': False }
-        response['error_type'] = 'Bad handle %d (only handle 0 ' + \
-                                 'is supported)' % handle
-        return response
-
-    # Find local event-channel port associated with the specified domain.
-    port = xend.main.port_from_dom(dom)
-    if not port:
-        response = { 'success': False }
-        response['error_type'] = 'Unknown domain %d' % dom
-        return response
-        
-    # The interface must exist.
-    if not xend.blkif.interface.list.has_key(port.local_port):
-        response = { 'success': False }
-        response['error_type'] = 'Interface (dom=%d,handle=%d) does not ' + \
-                                 'exists' % (dom, handle)
-        return response
-
-    # The virtual device must not yet exist.
-    blkif = xend.blkif.interface.list[port.local_port]
-    if not blkif.attach_device(vdev, pdev, start_sect, nr_sect, readonly):
-        response = { 'success': False }
-        response['error_type'] = 'Vdevice (dom=%d,handle=%d,vdevice=%d) ' + \
-                                 'already exists' % (dom, handle, vdev)
-        return response
-
-    # Response is deferred until back-end driver sends acknowledgement.
-    return None
-
-
-##
-## new_network_interface:
-##  Create a new network interface for the specified domain @dom.
-##
-def new_network_interface(dom, handle=-1):
-    # By default we create an interface with handle zero.
-    if handle < 0:
-        handle = 0
-
-    # We only support one interface per domain, which must have handle zero.
-    if handle != 0:
-        response = { 'success': False }
-        response['error_type'] = 'Bad handle %d (only handle 0 ' + \
-                                 'is supported)' % handle
-        return response
-
-    # Find local event-channel port associated with the specified domain.
-    port = xend.main.port_from_dom(dom)
-    if not port:
-        response = { 'success': False }
-        response['error_type'] = 'Unknown domain %d' % dom
-        return response
-
-    # The interface must not already exist.
-    if xend.netif.interface.list.has_key(port.local_port):
-        response = { 'success': False }
-        response['error_type'] = 'Interface (dom=%d,handle=%d) already ' + \
-                                 'exists' % (dom, handle)
-        return response
-
-    # Create the new interface. Initially no virtual devices are attached.
-    xend.netif.interface(dom, port.local_port)
-
-    # Response is deferred until back-end driver sends acknowledgement.
-    return None
-
-##
-## set_network_backend
-##   Authorise a domain to act as the net backend (assumes we only have one
-##   backend driver for now).  After this call, back end "up" notifications
-##   for the network will only be accepted from this domain.
-##
-def set_network_backend(dom):
-    if xend.netif.be_port.remote_dom != 0:
-        xend.netif.recovery = True
-    xend.netif.be_port = xend.main.port_from_dom(dom)
-    return { 'success' : True }
-
-##
-## set_block_backend
-##  Authorise a domain to act as the block backend (assumes we only have one
-##  backend driver for now).  After this call, back end "up" notifications
-##  for the network will only be accepted from this domain.
-def set_block_backend(dom):
-    if xend.blkif.be_port: xend.blkif.recovery = True
-    xend.blkif.be_port = xend.main.port_from_dom(dom)
-    return { 'success' : True }
diff --git a/tools/xend/lib/netif.py b/tools/xend/lib/netif.py
deleted file mode 100644 (file)
index eaa1008..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-
-###################################################################
-## xend/netif.py -- Network-interface management functions for Xend
-## Copyright (c) 2004, K A Fraser (University of Cambridge)
-###################################################################
-
-import errno, random, re, os, select, signal, socket, struct, sys
-import xend.main, xend.console, xend.manager, xend.utils, Xc
-
-CMSG_NETIF_BE = 3
-CMSG_NETIF_FE = 4
-CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED =  0
-CMSG_NETIF_FE_DRIVER_STATUS_CHANGED    = 32
-CMSG_NETIF_BE_DRIVER_STATUS_CHANGED    = 32
-CMSG_NETIF_FE_INTERFACE_CONNECT        = 33
-CMSG_NETIF_FE_INTERFACE_DISCONNECT     = 34
-CMSG_NETIF_BE_CREATE      = 0
-CMSG_NETIF_BE_DESTROY     = 1
-CMSG_NETIF_BE_CONNECT     = 2
-CMSG_NETIF_BE_DISCONNECT  = 3
-
-NETIF_DRIVER_STATUS_DOWN  = 0
-NETIF_DRIVER_STATUS_UP    = 1
-
-pendmsg = None
-pendaddr = None
-
-recovery = False # Is a recovery in progress?
-be_port  = None  # Port object for backend domain
-
-def backend_tx_req(msg):
-    if xend.netif.be_port.space_to_write_request():
-        xend.netif.be_port.write_request(msg)
-        xend.netif.be_port.notify()
-    else:
-        xend.netif.pendmsg = msg
-
-def backend_rx_req(port, msg):
-    port.write_response(msg)
-    subtype = (msg.get_header())['subtype']
-    print "Received netif-be request, subtype %d" % subtype
-    if subtype == CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
-        pl = msg.get_payload()
-        status = pl['status']
-        if status == NETIF_DRIVER_STATUS_UP:
-            if xend.netif.recovery:
-                print "New netif backend now UP, notifying guests:"
-                for netif_key in interface.list.keys():
-                    netif = interface.list[netif_key]
-                    netif.create()
-                    print "  Notifying %d" % netif.dom
-                    msg = xend.utils.message(
-                        CMSG_NETIF_FE,
-                        CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
-                        { 'handle' : 0, 'status' : 1 })
-                    netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom),msg)
-                print "Done notifying guests"
-                recovery = False
-        else:
-            print "Unexpected net backend driver status: %d" % status
-
-def backend_rx_rsp(port, msg):
-    subtype = (msg.get_header())['subtype']
-    print "Received netif-be response, subtype %d" % subtype
-    if subtype == CMSG_NETIF_BE_CREATE:
-        rsp = { 'success': True }
-        xend.main.send_management_response(rsp, xend.netif.pendaddr)
-    elif subtype == CMSG_NETIF_BE_CONNECT:
-        pl = msg.get_payload()
-        (dom, hnd, evtchn, tx_frame, rx_frame, st) = (
-            pl['domid'], pl['netif_handle'], pl['evtchn'],
-            pl['tx_shmem_frame'], pl['rx_shmem_frame'], pl['status'])
-        netif = interface.list[xend.main.port_from_dom(dom).local_port]
-        msg = xend.utils.message(CMSG_NETIF_FE,
-                                 CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
-                                 { 'handle' : 0, 'status' : 2,
-                                   'evtchn' : netif.evtchn['port2'],
-                                   'mac[0]' : netif.mac[0],
-                                   'mac[1]' : netif.mac[1],
-                                   'mac[2]' : netif.mac[2],
-                                   'mac[3]' : netif.mac[3],
-                                   'mac[4]' : netif.mac[4],
-                                   'mac[5]' : netif.mac[5] })
-        netif.ctrlif_tx_req(xend.main.port_list[netif.key], msg)
-
-def backend_do_work(port):
-    global pendmsg
-    if pendmsg and port.space_to_write_request():
-        port.write_request(pendmsg)
-        pendmsg = None
-        return True
-    return False
-
-
-class interface:
-
-    # Dictionary of all network-device interfaces.
-    list = {}
-
-    drvdom = None
-
-    # NB. 'key' is an opaque value that has no meaning in this class.
-    def __init__(self, dom, key):
-        self.dom     = dom
-        self.key     = key
-        self.pendmsg = None
-
-        # VIFs get a random MAC address with a "special" vendor id.
-        # 
-        # NB. The vendor is currently an "obsolete" one that used to belong
-        # to DEC (AA-00-00). Using it is probably a bit rude :-)
-        # 
-        # NB2. The first bit of the first random octet is set to zero for
-        # all dynamic MAC addresses. This may allow us to manually specify
-        # MAC addresses for some VIFs with no fear of clashes.
-        self.mac = [ 0xaa, 0x00, 0x00 ]
-        self.mac.append(int(random.random()*128))
-        self.mac.append(int(random.random()*256))
-        self.mac.append(int(random.random()*256))
-                
-        interface.list[key] = self
-        self.create()
-
-    def create(self):
-        """Notify the current network back end to create the virtual interface
-        represented by this object."""
-        msg = xend.utils.message(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE, 0,
-                                 { 'domid' : self.dom, 'netif_handle' : 0,
-                                   'mac[0]' : self.mac[0],
-                                   'mac[1]' : self.mac[1],
-                                   'mac[2]' : self.mac[2],
-                                   'mac[3]' : self.mac[3],
-                                   'mac[4]' : self.mac[4],
-                                   'mac[5]' : self.mac[5] })
-        xend.netif.pendaddr = xend.main.mgmt_req_addr
-        backend_tx_req(msg)
-
-
-    # Completely destroy this interface.
-    def destroy(self):
-        del interface.list[self.key]
-        msg = xend.utils.message(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY, 0,
-                                 { 'domid' : self.dom, 'netif_handle' : 0 })
-        backend_tx_req(msg)        
-
-
-    # The parameter @port is the control-interface event channel. This method
-    # returns True if messages were written to the control interface.
-    def ctrlif_transmit_work(self, port):
-        if self.pendmsg and port.space_to_write_request():
-            port.write_request(self.pendmsg)
-            self.pendmsg = None
-            return True
-        return False
-
-    def ctrlif_tx_req(self, port, msg):
-        if port.space_to_write_request():
-            port.write_request(msg)
-            port.notify()
-        else:
-            self.pendmsg = msg
-
-    def ctrlif_rx_req(self, port, msg):
-        port.write_response(msg)
-        subtype = (msg.get_header())['subtype']
-        if subtype == CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
-            print "netif driver up message from %d" % port.remote_dom
-            msg = xend.utils.message(CMSG_NETIF_FE,
-                                     CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
-                                     { 'handle' : 0, 'status' : 1 })
-            self.ctrlif_tx_req(port, msg)
-        elif subtype == CMSG_NETIF_FE_INTERFACE_CONNECT:
-            print "netif connect request from %d" % port.remote_dom
-            pl = msg.get_payload()
-            (hnd, tx_frame, rx_frame) = (pl['handle'], pl['tx_shmem_frame'],
-                                         pl['rx_shmem_frame'])
-            xc = Xc.new()
-            self.evtchn = xc.evtchn_bind_interdomain(
-                dom1=xend.netif.be_port.remote_dom,
-                dom2=self.dom)
-            msg = xend.utils.message(CMSG_NETIF_BE,
-                                     CMSG_NETIF_BE_CONNECT, 0,
-                                     { 'domid' : self.dom, 'netif_handle' : 0,
-                                       'tx_shmem_frame' : tx_frame,
-                                       'rx_shmem_frame' : rx_frame,
-                                       'evtchn' : self.evtchn['port1'] })
-            backend_tx_req(msg)
diff --git a/tools/xend/lib/utils.c b/tools/xend/lib/utils.c
deleted file mode 100644 (file)
index 2d96577..0000000
+++ /dev/null
@@ -1,1384 +0,0 @@
-/******************************************************************************
- * utils.c
- * 
- * Copyright (c) 2004, K A Fraser
- */
-
-#include <Python.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/mman.h>
-#include <sys/poll.h>
-#include <netinet/in.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <xc.h>
-
-#include <hypervisor-if.h>
-#include "domain_controller.h"
-
-#include <asm-xen/proc_cmd.h>
-
-/* Needed for Python versions earlier than 2.3. */
-#ifndef PyMODINIT_FUNC
-#define PyMODINIT_FUNC DL_EXPORT(void)
-#endif
-
-/* NB. The following should be kept in sync with the kernel's evtchn driver. */
-#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
-#define EVTCHN_DEV_MAJOR 10
-#define EVTCHN_DEV_MINOR 200
-#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
-#define PORT_EXCEPTION  0x8000   /* An exceptional notification.        */
-#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
-/* /dev/xen/evtchn ioctls: */
-/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
-#define EVTCHN_RESET  _IO('E', 1)
-/* EVTCHN_BIND: Bind to teh specified event-channel port. */
-#define EVTCHN_BIND   _IO('E', 2)
-/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
-#define EVTCHN_UNBIND _IO('E', 3)
-
-/* Size of a machine page frame. */
-#define PAGE_SIZE 4096
-
-
-/*
- * *********************** NOTIFIER ***********************
- */
-
-typedef struct {
-    PyObject_HEAD;
-    int evtchn_fd;
-} xu_notifier_object;
-
-static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    u16 v;
-    int bytes;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-    
-    while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
-    {
-        if ( errno == EINTR )
-            continue;
-        if ( errno == EAGAIN )
-            goto none;
-        return PyErr_SetFromErrno(PyExc_IOError);
-    }
-    
-    if ( bytes == sizeof(v) )
-        return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK);
-
- none:
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    u16 v;
-    int idx;
-
-    if ( !PyArg_ParseTuple(args, "i", &idx) )
-        return NULL;
-
-    v = (u16)idx;
-    
-    (void)write(xun->evtchn_fd, &v, sizeof(v));
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    int idx;
-
-    if ( !PyArg_ParseTuple(args, "i", &idx) )
-        return NULL;
-
-    if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
-        return PyErr_SetFromErrno(PyExc_IOError);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    int idx;
-
-    if ( !PyArg_ParseTuple(args, "i", &idx) )
-        return NULL;
-
-    if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
-        return PyErr_SetFromErrno(PyExc_IOError);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    return PyInt_FromLong(xun->evtchn_fd);
-}
-
-static PyMethodDef xu_notifier_methods[] = {
-    { "read",
-      (PyCFunction)xu_notifier_read,
-      METH_VARARGS,
-      "Read a (@port, @type) pair.\n" },
-
-    { "unmask", 
-      (PyCFunction)xu_notifier_unmask,
-      METH_VARARGS,
-      "Unmask notifications for a @port.\n" },
-
-    { "bind", 
-      (PyCFunction)xu_notifier_bind,
-      METH_VARARGS,
-      "Get notifications for a @port.\n" },
-
-    { "unbind", 
-      (PyCFunction)xu_notifier_unbind,
-      METH_VARARGS,
-      "No longer get notifications for a @port.\n" },
-
-    { "fileno", 
-      (PyCFunction)xu_notifier_fileno,
-      METH_VARARGS,
-      "Return the file descriptor for the notification channel.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_notifier_type;
-
-static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
-
- reopen:
-    xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
-    if ( xun->evtchn_fd == -1 )
-    {
-        if ( (errno == ENOENT) &&
-             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
-             (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, 
-                    (EVTCHN_DEV_MAJOR << 8) | EVTCHN_DEV_MINOR) == 0) )
-            goto reopen;
-        PyObject_Del((PyObject *)xun);
-        return PyErr_SetFromErrno(PyExc_IOError);
-    }
-
-    return (PyObject *)xun;
-}
-
-static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
-{
-    if ( strcmp(name, "EXCEPTION") == 0 )
-        return PyInt_FromLong(PORT_EXCEPTION);
-    if ( strcmp(name, "NORMAL") == 0 )
-        return PyInt_FromLong(PORT_NORMAL);
-    return Py_FindMethod(xu_notifier_methods, obj, name);
-}
-
-static void xu_notifier_dealloc(PyObject *self)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    (void)close(xun->evtchn_fd);
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_notifier_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "notifier",
-    sizeof(xu_notifier_object),
-    0,
-    xu_notifier_dealloc, /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_notifier_getattr, /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** MESSAGE ***********************
- */
-
-#define TYPE(_x,_y) (((_x)<<8)|(_y))
-#define P2C(_struct, _field, _ctype)                                      \
-    do {                                                                  \
-        PyObject *obj;                                                    \
-        if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL )     \
-        {                                                                 \
-            if ( PyInt_Check(obj) )                                       \
-            {                                                             \
-                ((_struct *)&xum->msg.msg[0])->_field =                   \
-                  (_ctype)PyInt_AsLong(obj);                              \
-                dict_items_parsed++;                                      \
-            }                                                             \
-            else if ( PyLong_Check(obj) )                                 \
-            {                                                             \
-                ((_struct *)&xum->msg.msg[0])->_field =                   \
-                  (_ctype)PyLong_AsUnsignedLongLong(obj);                 \
-                dict_items_parsed++;                                      \
-            }                                                             \
-        }                                                                 \
-        xum->msg.length = sizeof(_struct);                                \
-    } while ( 0 )
-#define C2P(_struct, _field, _pytype, _ctype)                             \
-    do {                                                                  \
-        PyObject *obj = Py ## _pytype ## _From ## _ctype                  \
-                        (((_struct *)&xum->msg.msg[0])->_field);          \
-        if ( dict == NULL ) dict = PyDict_New();                          \
-        PyDict_SetItemString(dict, #_field, obj);                         \
-    } while ( 0 )
-
-typedef struct {
-    PyObject_HEAD;
-    control_msg_t msg;
-} xu_message_object;
-
-static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    char *str;
-    int len;
-
-    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
-        return NULL;
-
-    if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
-    {
-        PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
-        return NULL;
-    }
-
-    memcpy(&xum->msg.msg[xum->msg.length], str, len);
-    xum->msg.length += len;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    PyObject *payload;
-    int dict_items_parsed = 0;
-
-    if ( !PyArg_ParseTuple(args, "O", &payload) )
-        return NULL;
-
-    if ( !PyDict_Check(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
-        return NULL;
-    }
-
-    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
-        break;
-    }
-
-    if ( dict_items_parsed != PyDict_Size(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
-        return NULL;
-    }
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    PyObject *dict = NULL;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
-        C2P(blkif_fe_interface_status_changed_t, handle, Int, Long);
-        C2P(blkif_fe_interface_status_changed_t, status, Int, Long);
-        C2P(blkif_fe_interface_status_changed_t, evtchn, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
-        C2P(blkif_fe_driver_status_changed_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
-        C2P(blkif_fe_interface_connect_t, handle,      Int, Long);
-        C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
-        C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
-        C2P(blkif_be_create_t, domid,        Int, Long);
-        C2P(blkif_be_create_t, blkif_handle, Int, Long);
-        C2P(blkif_be_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
-        C2P(blkif_be_destroy_t, domid,        Int, Long);
-        C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
-        C2P(blkif_be_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
-        C2P(blkif_be_connect_t, domid,        Int, Long);
-        C2P(blkif_be_connect_t, blkif_handle, Int, Long);
-        C2P(blkif_be_connect_t, shmem_frame,  Int, Long);
-        C2P(blkif_be_connect_t, evtchn,       Int, Long);
-        C2P(blkif_be_connect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
-        C2P(blkif_be_disconnect_t, domid,        Int, Long);
-        C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
-        C2P(blkif_be_disconnect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
-        C2P(blkif_be_vbd_create_t, domid,        Int, Long);
-        C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
-        C2P(blkif_be_vbd_create_t, vdevice,      Int, Long);
-        C2P(blkif_be_vbd_create_t, readonly,     Int, Long);
-        C2P(blkif_be_vbd_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
-        C2P(blkif_be_vbd_destroy_t, domid,        Int, Long);
-        C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
-        C2P(blkif_be_vbd_destroy_t, vdevice,      Int, Long);
-        C2P(blkif_be_vbd_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
-        C2P(blkif_be_vbd_grow_t, domid,         Int, Long);
-        C2P(blkif_be_vbd_grow_t, blkif_handle,  Int, Long);
-        C2P(blkif_be_vbd_grow_t, vdevice,       Int, Long);
-        C2P(blkif_be_vbd_grow_t, extent.sector_start, 
-             Long, UnsignedLongLong);
-        C2P(blkif_be_vbd_grow_t, extent.sector_length, 
-             Long, UnsignedLongLong);
-        C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
-        C2P(blkif_be_vbd_grow_t, status,        Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
-        C2P(blkif_be_vbd_shrink_t, domid,        Int, Long);
-        C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
-        C2P(blkif_be_vbd_shrink_t, vdevice,      Int, Long);
-        C2P(blkif_be_vbd_shrink_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED):
-        C2P(blkif_be_driver_status_changed_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
-        C2P(netif_fe_interface_status_changed_t, handle, Int, Long);
-        C2P(netif_fe_interface_status_changed_t, status, Int, Long);
-        C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        C2P(netif_fe_driver_status_changed_t, status,        Int, Long);
-        C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
-        C2P(netif_fe_interface_connect_t, handle,         Int, Long);
-        C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
-        C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
-        C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
-        C2P(netif_be_create_t, domid,        Int, Long);
-        C2P(netif_be_create_t, netif_handle, Int, Long);
-        C2P(netif_be_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
-        C2P(netif_be_destroy_t, domid,        Int, Long);
-        C2P(netif_be_destroy_t, netif_handle, Int, Long);
-        C2P(netif_be_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
-        C2P(netif_be_connect_t, domid,          Int, Long);
-        C2P(netif_be_connect_t, netif_handle,   Int, Long);
-        C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
-        C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
-        C2P(netif_be_connect_t, evtchn,         Int, Long);
-        C2P(netif_be_connect_t, status,         Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
-        C2P(netif_be_disconnect_t, domid,        Int, Long);
-        C2P(netif_be_disconnect_t, netif_handle, Int, Long);
-        C2P(netif_be_disconnect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED):
-        C2P(netif_be_driver_status_changed_t, status, Int, Long);
-        return dict;
-    }
-
-    return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
-}
-
-static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    return Py_BuildValue("{s:i,s:i,s:i}",
-                         "type",    xum->msg.type,
-                         "subtype", xum->msg.subtype,
-                         "id",      xum->msg.id);
-}
-
-static PyMethodDef xu_message_methods[] = {
-    { "append_payload", 
-      (PyCFunction)xu_message_append_payload,
-      METH_VARARGS,
-      "Append @str to the message payload.\n" },
-
-    { "set_response_fields",
-      (PyCFunction)xu_message_set_response_fields,
-      METH_VARARGS,
-      "Fill in the response fields in a message that was passed to us.\n" },
-
-    { "get_payload",
-      (PyCFunction)xu_message_get_payload,
-      METH_VARARGS,
-      "Return the message payload in string form.\n" },
-
-    { "get_header",
-      (PyCFunction)xu_message_get_header,
-      METH_VARARGS,
-      "Returns a dictionary of values for @type, @subtype, and @id.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_message_type;
-
-static PyObject *xu_message_new(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum;
-    int type, subtype, id, dict_items_parsed = 0;
-    PyObject *payload = NULL;
-
-    if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
-        return NULL;
-
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-
-    xum->msg.type    = type;
-    xum->msg.subtype = subtype;
-    xum->msg.id      = id;
-    xum->msg.length  = 0;
-
-    if ( payload == NULL )
-        return (PyObject *)xum;
-
-    if ( !PyDict_Check(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
-        PyObject_Del((PyObject *)xum);
-        return NULL;
-    }
-
-    switch ( TYPE(type, subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
-        P2C(blkif_fe_interface_status_changed_t, handle, u32);
-        P2C(blkif_fe_interface_status_changed_t, status, u32);
-        P2C(blkif_fe_interface_status_changed_t, evtchn, u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
-        P2C(blkif_be_create_t, domid,        u32);
-        P2C(blkif_be_create_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
-        P2C(blkif_be_destroy_t, domid,        u32);
-        P2C(blkif_be_destroy_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
-        P2C(blkif_be_connect_t, domid,        u32);
-        P2C(blkif_be_connect_t, blkif_handle, u32);
-        P2C(blkif_be_connect_t, shmem_frame,  memory_t);
-        P2C(blkif_be_connect_t, evtchn,       u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
-        P2C(blkif_be_disconnect_t, domid,        u32);
-        P2C(blkif_be_disconnect_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
-        P2C(blkif_be_vbd_create_t, domid,        u32);
-        P2C(blkif_be_vbd_create_t, blkif_handle, u32);
-        P2C(blkif_be_vbd_create_t, vdevice,      blkif_vdev_t);
-        P2C(blkif_be_vbd_create_t, readonly,     u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
-        P2C(blkif_be_vbd_destroy_t, domid,        u32);
-        P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
-        P2C(blkif_be_vbd_destroy_t, vdevice,      blkif_vdev_t);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
-        P2C(blkif_be_vbd_grow_t, domid,                u32);
-        P2C(blkif_be_vbd_grow_t, blkif_handle,         u32);
-        P2C(blkif_be_vbd_grow_t, vdevice,              blkif_vdev_t);
-        P2C(blkif_be_vbd_grow_t, extent.sector_start,  blkif_sector_t);
-        P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
-        P2C(blkif_be_vbd_grow_t, extent.device,        blkif_pdev_t);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
-        P2C(blkif_be_vbd_shrink_t, domid,        u32);
-        P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
-        P2C(blkif_be_vbd_shrink_t, vdevice,      blkif_vdev_t);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
-        P2C(netif_fe_interface_status_changed_t, handle, u32);
-        P2C(netif_fe_interface_status_changed_t, status, u32);
-        P2C(netif_fe_interface_status_changed_t, evtchn, u16);
-        P2C(netif_fe_interface_status_changed_t, mac[0], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[1], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[2], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[3], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[4], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[5], u8);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
-        P2C(netif_be_create_t, domid,        u32);
-        P2C(netif_be_create_t, netif_handle, u32);
-        P2C(netif_be_create_t, mac[0],       u8);
-        P2C(netif_be_create_t, mac[1],       u8);
-        P2C(netif_be_create_t, mac[2],       u8);
-        P2C(netif_be_create_t, mac[3],       u8);
-        P2C(netif_be_create_t, mac[4],       u8);
-        P2C(netif_be_create_t, mac[5],       u8);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
-        P2C(netif_be_destroy_t, domid,        u32);
-        P2C(netif_be_destroy_t, netif_handle, u32);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
-        P2C(netif_be_connect_t, domid,          u32);
-        P2C(netif_be_connect_t, netif_handle,   u32);
-        P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
-        P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
-        P2C(netif_be_connect_t, evtchn,         u16);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
-        P2C(netif_be_disconnect_t, domid,        u32);
-        P2C(netif_be_disconnect_t, netif_handle, u32);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(netif_fe_driver_status_changed_t, status,        u32);
-        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
-        break;
-    }
-
-    if ( dict_items_parsed != PyDict_Size(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
-        PyObject_Del((PyObject *)xum);
-        return NULL;
-    }
-
-    return (PyObject *)xum;
-}
-
-static PyObject *xu_message_getattr(PyObject *obj, char *name)
-{
-    xu_message_object *xum;
-    if ( strcmp(name, "MAX_PAYLOAD") == 0 )
-        return PyInt_FromLong(sizeof(xum->msg.msg));
-    return Py_FindMethod(xu_message_methods, obj, name);
-}
-
-static void xu_message_dealloc(PyObject *self)
-{
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_message_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "message",
-    sizeof(xu_message_object),
-    0,
-    xu_message_dealloc,   /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_message_getattr,   /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** PORT ***********************
- */
-
-static control_if_t *map_control_interface(int fd, unsigned long pfn)
-{
-    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
-                       MAP_SHARED, fd, pfn * PAGE_SIZE);
-    if ( vaddr == MAP_FAILED )
-        return NULL;
-    return (control_if_t *)(vaddr + 2048);
-}
-static void unmap_control_interface(int fd, control_if_t *c)
-{
-    char *vaddr = (char *)c - 2048;
-    (void)munmap(vaddr, PAGE_SIZE);
-}
-
-typedef struct xu_port_object {
-    PyObject_HEAD;
-    int mem_fd;
-    int xc_handle;
-    u32 remote_dom;
-    int local_port, remote_port;
-    control_if_t    *interface;
-    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
-    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
-} xu_port_object;
-
-static PyObject *port_error;
-
-static int xup_connect(xu_port_object *xup, domid_t dom,
-                       int local_port, int remote_port){
-    // From our prespective rx = producer, tx = consumer.
-    int err = 0;
-    printf("%s> dom=%u %d:%d\n", __FUNCTION__, (unsigned int)dom, 
-           local_port, remote_port);
-
-    // Consumer = tx.
-    //xup->interface->tx_resp_prod = 0;
-    //xup->interface->tx_req_prod = 0;
-    xup->tx_resp_prod = xup->interface->tx_resp_prod;
-    xup->tx_req_cons = xup->interface->tx_resp_prod;
-    printf("%s> tx: %u %u : %u %u\n", __FUNCTION__,
-           (unsigned int)xup->interface->tx_resp_prod,
-           (unsigned int)xup->tx_resp_prod,
-           (unsigned int)xup->tx_req_cons,
-           (unsigned int)xup->interface->tx_req_prod);
-
-    // Producer = rx.
-    //xup->interface->rx_req_prod  = 0;
-    //xup->interface->rx_resp_prod = 0;
-    xup->rx_req_prod  = xup->interface->rx_req_prod;
-    xup->rx_resp_cons = xup->interface->rx_resp_prod;
-    printf("%s> rx: %u %u : %u %u\n", __FUNCTION__,
-           (unsigned int)xup->rx_resp_cons,
-           (unsigned int)xup->interface->rx_resp_prod,
-           (unsigned int)xup->interface->rx_req_prod,
-           (unsigned int)xup->rx_req_prod);
-
-    xup->remote_dom   = dom;
-    xup->local_port   = local_port;
-    xup->remote_port  = remote_port;
-
-    printf("%s< err=%d\n", __FUNCTION__, err);
-    return err;
-}
-
-static PyObject *xu_port_notify(PyObject *self, PyObject *args)
-{
-    xu_port_object *xup = (xu_port_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   c = xup->tx_req_cons;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->tx_req_prod) || 
-         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
-    {
-        PyErr_SetString(port_error, "no request to read");
-        return NULL;
-    }
-
-    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
-    if ( xum->msg.length > sizeof(xum->msg.msg) )
-        xum->msg.length = sizeof(xum->msg.msg);
-    xup->tx_req_cons++;
-    return (PyObject *)xum;
-}
-
-static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   p = xup->rx_req_prod;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
-        return NULL;
-
-    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
-    {
-        PyErr_SetString(PyExc_TypeError, "expected a xend.utils.message");
-        return NULL;        
-    }
-
-    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
-    {
-        PyErr_SetString(port_error, "no space to write request");
-        return NULL;
-    }
-
-    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
-    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
-
-    xup->rx_req_prod = cif->rx_req_prod = p + 1;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   c = xup->rx_resp_cons;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
-    {
-        PyErr_SetString(port_error, "no response to read");
-        return NULL;
-    }
-
-    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
-    if ( xum->msg.length > sizeof(xum->msg.msg) )
-        xum->msg.length = sizeof(xum->msg.msg);
-    xup->rx_resp_cons++;
-    return (PyObject *)xum;
-}
-
-static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   p = xup->tx_resp_prod;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
-        return NULL;
-
-    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
-    {
-        PyErr_SetString(PyExc_TypeError, "expected a xend.utils.message");
-        return NULL;        
-    }
-
-    if ( p == xup->tx_req_cons )
-    {
-        PyErr_SetString(port_error, "no space to write response");
-        return NULL;
-    }
-
-    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
-    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
-
-    xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   c = xup->tx_req_cons;
-    control_if_t      *cif = xup->interface;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->tx_req_prod) || 
-         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   p = xup->rx_req_prod;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   c = xup->rx_resp_cons;
-    control_if_t      *cif = xup->interface;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_space_to_write_response(
-    PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   p = xup->tx_resp_prod;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( p == xup->tx_req_cons )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyMethodDef xu_port_methods[] = {
-    { "notify",
-      (PyCFunction)xu_port_notify,
-      METH_VARARGS,
-      "Send a notification to the remote end.\n" },
-
-    { "read_request",
-      (PyCFunction)xu_port_read_request,
-      METH_VARARGS,
-      "Read a request message from the control interface.\n" },
-
-    { "write_request",
-      (PyCFunction)xu_port_write_request,
-      METH_VARARGS,
-      "Write a request message to the control interface.\n" },
-
-    { "read_response",
-      (PyCFunction)xu_port_read_response,
-      METH_VARARGS,
-      "Read a response message from the control interface.\n" },
-
-    { "write_response",
-      (PyCFunction)xu_port_write_response,
-      METH_VARARGS,
-      "Write a response message to the control interface.\n" },
-
-    { "request_to_read",
-      (PyCFunction)xu_port_request_to_read,
-      METH_VARARGS,
-      "Returns TRUE if there is a request message to read.\n" },
-
-    { "space_to_write_request",
-      (PyCFunction)xu_port_space_to_write_request,
-      METH_VARARGS,
-      "Returns TRUE if there is space to write a request message.\n" },
-
-    { "response_to_read",
-      (PyCFunction)xu_port_response_to_read,
-      METH_VARARGS,
-      "Returns TRUE if there is a response message to read.\n" },
-
-    { "space_to_write_response",
-      (PyCFunction)xu_port_space_to_write_response,
-      METH_VARARGS,
-      "Returns TRUE if there is space to write a response message.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_port_type;
-
-static PyObject *xu_port_new(PyObject *self, PyObject *args)
-{
-    xu_port_object *xup;
-    u32 dom;
-    int port1, port2;
-    xc_dominfo_t info;
-
-    if ( !PyArg_ParseTuple(args, "i", &dom) )
-        return NULL;
-
-    xup = PyObject_New(xu_port_object, &xu_port_type);
-
-    if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 )
-    {
-        PyErr_SetString(port_error, "Could not open '/dev/mem'");
-        goto fail1;
-    }
-
-    /* Set the General-Purpose Subject whose page frame will be mapped. */
-    (void)ioctl(xup->mem_fd, _IO('M', 1), (unsigned long)dom);
-
-    if ( (xup->xc_handle = xc_interface_open()) == -1 )
-    {
-        PyErr_SetString(port_error, "Could not open Xen control interface");
-        goto fail2;
-    }
-
-    if ( dom == 0 )
-    {
-        /*
-         * The control-interface event channel for DOM0 is already set up.
-         * We use an ioctl to discover the port at our end of the channel.
-         */
-        port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
-        port2 = -1; /* We don't need the remote end of the DOM0 link. */
-        if ( port1 < 0 )
-        {
-            PyErr_SetString(port_error, "Could not open channel to DOM0");
-            goto fail3;
-        }
-    }
-    else if ( xc_evtchn_bind_interdomain(xup->xc_handle, 
-                                         DOMID_SELF, dom, 
-                                         &port1, &port2) != 0 )
-    {
-        PyErr_SetString(port_error, "Could not open channel to domain");
-        goto fail3;
-    }
-
-    if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) ||
-         (info.domid != dom) )
-    {
-        PyErr_SetString(port_error, "Failed to obtain domain status");
-        goto fail4;
-    }
-
-    xup->interface = 
-        map_control_interface(xup->mem_fd, info.shared_info_frame);
-    if ( xup->interface == NULL )
-    {
-        PyErr_SetString(port_error, "Failed to map domain control interface");
-        goto fail4;
-    }
-
-    xup_connect(xup, dom, port1, port2);
-    return (PyObject *)xup;
-
-    
- fail4:
-    (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
- fail3:
-    (void)xc_interface_close(xup->xc_handle);
- fail2:
-    (void)close(xup->mem_fd);
- fail1:
-    PyObject_Del((PyObject *)xup);
-    return NULL;        
-}
-
-static PyObject *xu_port_getattr(PyObject *obj, char *name)
-{
-    xu_port_object *xup = (xu_port_object *)obj;
-    if ( strcmp(name, "local_port") == 0 )
-        return PyInt_FromLong(xup->local_port);
-    if ( strcmp(name, "remote_port") == 0 )
-        return PyInt_FromLong(xup->remote_port);
-    if ( strcmp(name, "remote_dom") == 0 )
-        return PyInt_FromLong(xup->remote_dom);
-    return Py_FindMethod(xu_port_methods, obj, name);
-}
-
-static void xu_port_dealloc(PyObject *self)
-{
-    xu_port_object *xup = (xu_port_object *)self;
-    unmap_control_interface(xup->mem_fd, xup->interface);
-    if ( xup->remote_dom != 0 )
-        (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
-    (void)xc_interface_close(xup->xc_handle);
-    (void)close(xup->mem_fd);
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_port_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "port",
-    sizeof(xu_port_object),
-    0,
-    xu_port_dealloc,     /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_port_getattr,     /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** BUFFER ***********************
- */
-
-#define BUFSZ 65536
-#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
-typedef unsigned int BUF_IDX;
-
-typedef struct {
-    PyObject_HEAD;
-    char        *buf;
-    unsigned int prod, cons;
-} xu_buffer_object;
-
-static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
-{
-    PyObject *str1, *str2;
-    int len1, len2, c = MASK_BUF_IDX(xub->cons);
-
-    len1 = xub->prod - xub->cons;
-    if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
-        len1 = BUFSZ - c;
-    if ( len1 > max )         /* clip to specified maximum */
-        len1 = max;
-    if ( len1 < 0 )           /* sanity */
-        len1 = 0;
-
-    if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
-        return NULL;
-
-    if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
-    {
-        len2 = max - len1;
-        if ( len2 > MASK_BUF_IDX(xub->prod) )
-            len2 = MASK_BUF_IDX(xub->prod);
-        if ( len2 > 0 )
-        {
-            str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
-            if ( str2 == NULL )
-                return NULL;
-            PyString_ConcatAndDel(&str1, str2);
-            if ( str1 == NULL )
-                return NULL;
-        }
-    }
-
-    return str1;
-}
-
-static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    int max = 1024;
-
-    if ( !PyArg_ParseTuple(args, "|i", &max) )
-        return NULL;
-    
-    return __xu_buffer_peek(xub, max);
-}
-
-static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    PyObject *str;
-    int max = 1024;
-
-    if ( !PyArg_ParseTuple(args, "|i", &max) )
-        return NULL;
-
-    if ( (str = __xu_buffer_peek(xub, max)) != NULL )
-        xub->cons += PyString_Size(str);
-
-    return str;
-}
-
-static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    int max, len;
-
-    if ( !PyArg_ParseTuple(args, "i", &max) )
-        return NULL;
-
-    len = xub->prod - xub->cons;
-    if ( len > max )
-        len = max;
-    if ( len < 0 )
-        len = 0;
-
-    xub->cons += len;
-
-    return PyInt_FromLong(len);
-}
-
-static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    char *str;
-    int len, len1, len2;
-
-    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
-        return NULL;
-
-    len1 = len;
-    if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
-        len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
-    if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
-        len1 = BUFSZ - (xub->prod - xub->cons);
-
-    if ( len1 == 0 )
-        return PyInt_FromLong(0);
-
-    memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
-    xub->prod += len1;
-
-    if ( len1 < len )
-    {
-        len2 = len - len1;
-        if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
-            len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
-        if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
-            len2 = BUFSZ - (xub->prod - xub->cons);
-        if ( len2 != 0 )
-        {
-            memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
-            xub->prod += len2;
-            return PyInt_FromLong(len1 + len2);
-        }
-    }
-
-    return PyInt_FromLong(len1);
-}
-
-static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( xub->cons == xub->prod )
-        return PyInt_FromLong(1);
-
-    return PyInt_FromLong(0);
-}
-
-static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (xub->prod - xub->cons) == BUFSZ )
-        return PyInt_FromLong(1);
-
-    return PyInt_FromLong(0);
-}
-
-static PyMethodDef xu_buffer_methods[] = {
-    { "peek", 
-      (PyCFunction)xu_buffer_peek,
-      METH_VARARGS,
-      "Peek up to @max bytes from the buffer. Returns a string.\n" },
-
-    { "read", 
-      (PyCFunction)xu_buffer_read,
-      METH_VARARGS,
-      "Read up to @max bytes from the buffer. Returns a string.\n" },
-
-    { "discard", 
-      (PyCFunction)xu_buffer_discard,
-      METH_VARARGS,
-      "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
-
-    { "write", 
-      (PyCFunction)xu_buffer_write,
-      METH_VARARGS,
-      "Write @string into buffer. Return number of bytes written.\n" },
-
-    { "empty", 
-      (PyCFunction)xu_buffer_empty,
-      METH_VARARGS,
-      "Return TRUE if the buffer is empty.\n" },
-
-    { "full", 
-      (PyCFunction)xu_buffer_full,
-      METH_VARARGS,
-      "Return TRUE if the buffer is full.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_buffer_type;
-
-static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
-
-    if ( (xub->buf = malloc(BUFSZ)) == NULL )
-    {
-        PyObject_Del((PyObject *)xub);
-        return NULL;
-    }
-
-    xub->prod = xub->cons = 0;
-
-    return (PyObject *)xub;
-}
-
-static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
-{
-    return Py_FindMethod(xu_buffer_methods, obj, name);
-}
-
-static void xu_buffer_dealloc(PyObject *self)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    free(xub->buf);
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_buffer_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "buffer",
-    sizeof(xu_buffer_object),
-    0,
-    xu_buffer_dealloc,   /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_buffer_getattr,   /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** MODULE WRAPPER ***********************
- */
-
-static void handle_child_death(int dummy)
-{
-    while ( waitpid(-1, NULL, WNOHANG) > 0 )
-        continue;
-}
-
-static PyObject *xu_autoreap(PyObject *self, PyObject *args)
-{
-    struct sigaction sa;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    memset(&sa, 0, sizeof(sa));
-    sa.sa_handler = handle_child_death;
-    sigemptyset(&sa.sa_mask);
-    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
-    (void)sigaction(SIGCHLD, &sa, NULL);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyMethodDef xu_methods[] = {
-    { "notifier", xu_notifier_new, METH_VARARGS, 
-      "Create a new notifier." },
-    { "message", xu_message_new, METH_VARARGS, 
-      "Create a new communications message." },
-    { "port", xu_port_new, METH_VARARGS, 
-      "Create a new communications port." },
-    { "buffer", xu_buffer_new, METH_VARARGS, 
-      "Create a new ring buffer." },
-    { "autoreap", xu_autoreap, METH_VARARGS,
-      "Ensure that zombie children are automatically reaped by the OS." },
-    { NULL, NULL, 0, NULL }
-};
-
-PyMODINIT_FUNC initutils(void)
-{
-    PyObject *m, *d;
-
-    m = Py_InitModule("xend.utils", xu_methods);
-
-    d = PyModule_GetDict(m);
-    port_error = PyErr_NewException("xend.utils.PortError", NULL, NULL);
-    PyDict_SetItemString(d, "PortError", port_error);
-}
diff --git a/tools/xend/setup.py b/tools/xend/setup.py
deleted file mode 100644 (file)
index 66ed7a9..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-
-from distutils.core import setup, Extension
-
-utils = Extension("utils",
-                  extra_compile_args   = ["-fno-strict-aliasing"],
-                  include_dirs         = ["../xc/lib",
-                                          "../../xen/include/hypervisor-ifs",
-                                          "../../linux-xen-sparse/include"],
-                  library_dirs         = ["../xc/lib"],
-                  libraries            = ["xc"],
-                  sources              = ["lib/utils.c"])
-
-setup(name = "xend",
-      version = "1.0",
-      packages = ["xend"],
-      package_dir = { "xend" : "lib" },
-      ext_package = "xend",
-      ext_modules = [ utils ]
-      )
diff --git a/tools/xend/xend b/tools/xend/xend
deleted file mode 100755 (executable)
index 6e321bb..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python
-
-import os, sys, xend.main
-
-def main():
-    if not sys.argv[1:]:
-        print 'usage: %s {start|stop|restart}' % sys.argv[0]
-    elif os.fork():
-        pid, status = os.wait()
-        return status >> 8
-    elif sys.argv[1] == 'start':
-        return xend.main.start_daemon()
-    elif sys.argv[1] == 'stop':
-        return xend.main.stop_daemon()
-    elif sys.argv[1] == 'restart':
-        return xend.main.stop_daemon() or xend.main.start_daemon()
-    else:
-        print 'not an option:', sys.argv[1]
-    return 1
-
-if __name__ == '__main__':
-    sys.exit(main())
diff --git a/tools/xenmgr/Makefile b/tools/xenmgr/Makefile
deleted file mode 100644 (file)
index 642cd22..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-
-all:
-       python setup.py build
-
-install: all
-       if [ "$(prefix)" = "" ]; then                   \
-           python setup.py install;                    \
-       elif [ "$(dist)" = "yes" ]; then                \
-           python setup.py install --home="$(prefix)"; \
-       else                                            \
-           python setup.py install --root="$(prefix)"; \
-       fi
-       mkdir -p $(prefix)/usr/sbin
-       install -m0755 xend $(prefix)/usr/sbin
-       install -m0755 netfix $(prefix)/usr/sbin
-       install -m0755 xm $(prefix)/usr/sbin
-
-clean:
-       rm -rf build *.pyc *.pyo *.o *.a *~
diff --git a/tools/xenmgr/lib/Args.py b/tools/xenmgr/lib/Args.py
deleted file mode 100644 (file)
index 527e841..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-import sxp
-
-class ArgError(StandardError):
-    pass
-
-class Args:
-    """Argument encoding support for HTTP.
-    """
-    
-    def __init__(self, paramspec, keyspec):
-        self.arg_ord = []
-        self.arg_dict = {}
-        self.key_ord = []
-        self.key_dict = {}
-        for (name, type) in paramspec:
-                self.arg_ord.append(name)
-                self.arg_dict[name] = type
-        for (name, type) in keyspec:
-                self.key_ord.append(name)
-                self.key_dict[name] = type
-
-    def get_args(self, d, xargs=None):
-        args = {}
-        keys = {}
-        params = []
-        if xargs:
-            self.split_args(xargs, args, keys)
-        self.split_args(d, args, keys)
-        for a in self.arg_ord:
-            if a in args:
-                params.append(args[a])
-            else:
-                raise ArgError('Missing parameter: %s' % a)
-        return (params, keys)
-
-    def split_args(self, d, args, keys):
-        for (k, v) in d.items():
-            if k in self.arg_dict:
-                type = self.arg_dict[k]
-                val = self.coerce(type, v)
-                args[k] = val
-            elif k in self.key_dict:
-                type = self.key_dict[k]
-                val = self.coerce(type, v)
-                keys[k] = val
-            else:
-                raise ArgError('Invalid parameter: %s' % k)
-
-    def get_form_args(self, f, xargs=None):
-        d = {}
-        for (k, v) in f.items():
-            n = len(v)
-            if ((k not in self.arg_dict) and
-                (k not in self.key_dict)):
-                continue
-            if n == 0:
-                continue
-            elif n == 1:
-                d[k] = v[0]
-            else:
-                raise ArgError('Too many values for %s' % k)
-        return self.get_args(d, xargs=xargs)
-
-    def coerce(self, type, v):
-        try:
-            if type == 'int':
-                return int(v)
-            if type == 'str':
-                return str(v)
-            if type == 'sxpr':
-                return self.sxpr(v)
-        except ArgError:
-            raise
-        except StandardError, ex:
-            raise ArgError(str(ex))
-
-    def sxpr(self, v):
-        if instanceof(v, types.ListType):
-            return v
-        if instanceof(v, types.File) or hasattr(v, 'readline'):
-            return sxpr_file(v)
-        if instanceof(v, types.StringType):
-            return sxpr_file(StringIO(v))
-        return str(v)
-
-    def sxpr_file(self, fin):
-        try:
-            vals = sxp.parse(fin)
-        except:
-            raise ArgError('Coercion to sxpr failed')
-        if len(vals) == 1:
-            return vals[0]
-        else:
-            raise ArgError('Too many sxprs')
-
-    def call_with_args(self, fn, args, xargs=None):
-        (params, keys) = self.get_args(args, xargs=xargs)
-        fn(*params, **keys)
-
-    def call_with_form_args(self, fn, fargs, xargs=None):
-        (params, keys) = self.get_form_args(fargs, xargs=xargs)
-        fn(*params, **keys)
-
-class ArgFn(Args):
-    """Represent a remote HTTP operation as a function.
-    Used on the client.
-    """
-
-    def __init__(self, fn, paramspec, keyspec={}):
-        Args.__init__(self, paramspec, keyspec)
-        self.fn = fn
-
-    def __call__(self, fargs, xargs=None):
-        return self.call_with_args(self.fn, fargs, xargs=xargs)
-    
-class FormFn(Args):
-    """Represent an operation as a function over a form.
-    Used in the HTTP server.
-    """
-
-    def __init__(self, fn, paramspec, keyspec={}):
-        Args.__init__(self, paramspec, keyspec)
-        self.fn = fn
-
-    def __call__(self, fargs, xargs=None):
-        return self.call_with_form_args(self.fn, fargs, xargs=xargs)
diff --git a/tools/xenmgr/lib/EventServer.py b/tools/xenmgr/lib/EventServer.py
deleted file mode 100644 (file)
index 20c567a..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Simple publish/subscribe event server.
-
-"""
-import string
-
-from twisted.internet import reactor
-
-# subscribe a.b.c h: map a.b.c -> h
-# subscribe a.b.* h: map a.b.* -> h
-# subscribe a.b.? h: map a.b.? -> h
-#
-# for event a.b.c.d:
-#
-# lookup a.b.c.d, call handlers
-#
-# lookup a.b.c.?, call handlers
-#
-# lookup a.b.c.d.*, call handlers
-# lookup a.b.c.*, call handlers
-# lookup a.b.*, call handlers
-# lookup a.*, call handlers
-# lookup *, call handlers
-
-# a.b.c.d = (a b c d)
-# a.b.c.? = (a b c _)
-# a.b.c.* = (a b c . _)
-
-class EventServer:
-
-    DOT = '.'
-    QUERY = '?'
-    DOT_QUERY = DOT + QUERY
-    STAR = '*'
-    DOT_STAR = DOT + STAR
-
-    def __init__(self, run=0):
-        self.handlers = {}
-        self.run = run
-        self.queue = []
-
-    def start(self):
-        """Enable event handling. Sends any queued events.
-        """
-        self.run = 1
-        for (e,v) in self.queue:
-            self.inject(e, v)
-        self.queue = []
-
-    def stop(self):
-        """Suspend event handling. Events injected while suspended
-        are queued until we are started again.
-        """
-        self.run = 0
-
-    def subscribe(self, event, handler):
-        """Subscribe to an event. For example 'a.b.c.d'.
-        A subcription like 'a.b.c.?' ending in '?' matches any value
-        for the '?'. A subscription like 'a.b.c.*' ending in '*' matches
-        any event type with the same prefix, 'a.b.c' in this case.
-
-        event  event name
-        handler event handler fn(event, val)
-        """
-        hl = self.handlers.get(event)
-        if hl is None:
-            self.handlers[event] = [handler]
-        else:
-            hl.append(handler)
-
-    def unsubscribe_all(self, event=None):
-        """Unsubscribe all handlers for a given event, or all handlers.
-
-        event  event (optional)
-        """
-        if event == None:
-            self.handlers.clear()
-        elif event in self.handlers:
-            del self.handlers[event]
-        
-    def unsubscribe(self, event, handler):
-        """Unsubscribe a given event and handler.
-
-        event  event
-        handler handler
-        """
-        hl = self.handlers.get(event)
-        if hl is None:
-            return
-        if handler in hl:
-            hl.remove(handler)
-
-    def inject(self, event, val, async=1):
-        """Inject an event. Handlers for it are called if running, otherwise
-        it is queued.
-
-        event  event type
-        val    event value
-        """
-        if self.run:
-            if async:
-                reactor.callLater(0, self.call_handlers, event, val)
-            else:
-                self.notify_handlers(event, val)
-        else:
-            self.queue.append( (event, val) )
-
-    def call_handlers(self, event, val):
-        """Internal method to call event handlers.
-        """
-        #print ">event", event, val
-        self.call_event_handlers(event, event, val)
-        self.call_query_handlers(event, val)
-        self.call_star_handlers(event, val)
-
-    def call_event_handlers(self, key, event, val):
-        """Call the handlers for an event.
-        It is safe for handlers to subscribe or unsubscribe.
-
-        key    key for handler list
-        event  event type
-        val    event value
-        """
-        hl = self.handlers.get(key)
-        if hl is None:
-            return
-        # Copy the handler list so that handlers can call
-        # subscribe/unsubscribe safely - python list iteration
-        # is not safe against list modification.
-        for h in hl[:]:
-            try:
-                h(event, val)
-            except:
-                pass
-        
-    def call_query_handlers(self, event, val):
-        """Call regex handlers for events matching 'event' that end in '?'.
-
-        event  event type
-        val    event value
-        """
-        dot_idx = event.rfind(self.DOT)
-        if dot_idx == -1:
-            self.call_event_handlers(self.QUERY, event, val)
-        else:
-            event_query = event[0:dot_idx] + self.DOT_QUERY
-            self.call_event_handlers(event_query, event, val)
-
-    def call_star_handlers(self, event, val):
-        """Call regex handlers for events matching 'event' that end in '*'.
-
-        event  event type
-        val    event value
-        """
-        etype = string.split(event, self.DOT)
-        for i in range(len(etype), 0, -1):
-            event_star = self.DOT.join(etype[0:i]) + self.DOT_STAR
-            self.call_event_handlers(event_star, event, val)
-        self.call_event_handlers(self.STAR, event, val)       
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = EventServer()
-        inst.start()
-    return inst
-
-def main():
-    def sys_star(event, val):
-        print 'sys_star', event, val
-
-    def sys_foo(event, val):
-        print 'sys_foo', event, val
-        s.unsubscribe('sys.foo', sys_foo)
-
-    def sys_foo2(event, val):
-        print 'sys_foo2', event, val
-
-    def sys_bar(event, val):
-        print 'sys_bar', event, val
-
-    def sys_foo_bar(event, val):
-        print 'sys_foo_bar', event, val
-
-    def foo_bar(event, val):
-        print 'foo_bar', event, val
-
-    s = EventServer()
-    s.start()
-    s.subscribe('sys.*', sys_star)
-    s.subscribe('sys.foo', sys_foo)
-    s.subscribe('sys.foo', sys_foo2)
-    s.subscribe('sys.bar', sys_bar)
-    s.subscribe('sys.foo.bar', sys_foo_bar)
-    s.subscribe('foo.bar', foo_bar)
-    s.inject('sys.foo', 'hello')
-    print
-    s.inject('sys.bar', 'hello again')
-    print
-    s.inject('sys.foo.bar', 'hello again')
-    print
-    s.inject('foo.bar', 'hello again')
-    print
-    s.inject('foo', 'hello again')
-    print
-    s.start()
-    s.unsubscribe('sys.*', sys_star)
-    s.unsubscribe_all('sys.*')
-    s.inject('sys.foo', 'hello')
-
-if __name__ == "__main__":
-    main()
-
diff --git a/tools/xenmgr/lib/EventTypes.py b/tools/xenmgr/lib/EventTypes.py
deleted file mode 100644 (file)
index 6350baa..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#   Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-## XEND_DOMAIN_CREATE = "xend.domain.create": dom
-## create: 
-## xend.domain.destroy: dom, reason:died/crashed
-## xend.domain.up ?
-
-## xend.domain.unpause: dom
-## xend.domain.pause: dom
-## xend.domain.shutdown: dom
-## xend.domain.destroy: dom
-
-## xend.domain.migrate.begin: dom, to
-## Begin tells: src host, src domain uri, dst host. Dst id known?
-## err: src host, src domain uri, dst host, dst id if known, status (of domain: ok, dead,...), reason
-## end: src host, src domain uri, dst host, dst uri
-
-## Events for both ends of migrate: for exporter and importer?
-## Include migrate id so can tie together.
-## Have uri /xend/migrate/<id> for migrate info (migrations in progress).
-
-## (xend.domain.migrate.begin (src <host>) (src.domain <id>)
-##                            (dst <host>) (id <migrate id>))
-## xend.domain.migrate.end:
-## (xend.domain.migrate.end (domain <id>) (to <host>)
-
-## xend.node.up:  xend uri
-## xend.node.down: xend uri
-
-## xend.error ?
-
-## format:
-
diff --git a/tools/xenmgr/lib/PrettyPrint.py b/tools/xenmgr/lib/PrettyPrint.py
deleted file mode 100644 (file)
index 9e91b11..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""General pretty-printer, including support for SXP.
-
-"""
-import sys
-import types
-import StringIO
-import sxp
-
-class PrettyItem:
-
-    def __init__(self, width):
-        self.width = width
-
-    def insert(self, block):
-        block.addtoline(self)
-
-    def get_width(self):
-        return self.width
-
-    def output(self, out):
-        print '***PrettyItem>output>', self
-        pass
-
-    def prettyprint(self, out, width):
-        print '***PrettyItem>prettyprint>', self
-        return width
-
-class PrettyString(PrettyItem):
-
-    def __init__(self, x):
-        PrettyItem.__init__(self, len(x))
-        self.value = x
-
-    def output(self, out):
-        out.write(self.value)
-
-    def prettyprint(self, line):
-        line.output(self)
-
-    def show(self, out):
-        print >> out, ("(string (width %d) '%s')" % (self.width, self.value))
-
-class PrettySpace(PrettyItem):
-
-    def output(self, out):
-        out.write(' ' * self.width)
-
-    def prettyprint(self, line):
-        line.output(self)
-
-    def show(self, out):
-        print >> out, ("(space (width %d))" % self.width)
-        
-class PrettyBreak(PrettyItem):
-
-    def __init__(self, width, indent):
-        PrettyItem.__init__(self, width)
-        self.indent = indent
-        self.space = 0
-        self.active = 0
-
-    def output(self, out):
-        out.write(' ' * self.width)
-
-    def prettyprint(self, line):
-        if line.breaks(self.space):
-            self.active = 1
-            line.newline(self.indent)
-        else:
-            line.output(self)
-
-    def show(self, out):
-        print >> out, ("(break (width %d) (indent %d) (space %d) (active %d))"
-                       % (self.width, self.indent, self.space, self.lspace, self.active))
-
-class PrettyNewline(PrettySpace):
-
-    def __init__(self, indent):
-        PrettySpace.__init__(self, indent)
-
-    def insert(self, block):
-        block.newline()
-        block.addtoline(self)
-
-    def output(self, out):
-        out.write(' ' * self.width)
-
-    def prettyprint(self, line):
-        line.newline(0)
-        line.output(self)
-
-    def show(self, out):
-        print >> out, ("(nl (indent %d))" % self.indent)
-
-class PrettyLine(PrettyItem):
-    def __init__(self):
-        PrettyItem.__init__(self, 0)
-        self.content = []
-
-    def write(self, x):
-        self.content.append(x)
-
-    def end(self):
-        width = 0
-        lastwidth = 0
-        lastbreak = None
-        for x in self.content:
-            if isinstance(x, PrettyBreak):
-                if lastbreak:
-                    lastbreak.space = (width - lastwidth)
-                lastbreak = x
-                lastwidth = width
-            width += x.get_width()
-        if lastbreak:
-            lastbreak.space = (width - lastwidth)
-        self.width = width
-    def prettyprint(self, line):
-        for x in self.content:
-            x.prettyprint(line)
-
-    def show(self, out):
-        print >> out, '(LINE (width %d)' % self.width
-        for x in self.content:
-            x.show(out)
-        print >> out, ')'
-
-class PrettyBlock(PrettyItem):
-
-    def __init__(self, all=0, parent=None):
-        self.width = 0
-        self.lines = []
-        self.parent = parent
-        self.indent = 0
-        self.all = all
-        self.broken = 0
-        self.newline()
-
-    def add(self, item):
-        item.insert(self)
-
-    def end(self):
-        self.width = 0
-        for l in self.lines:
-            l.end()
-            if self.width < l.width:
-                self.width = l.width
-
-    def breaks(self, n):
-        return self.all and self.broken
-
-    def newline(self):
-        self.lines.append(PrettyLine())
-
-    def addtoline(self, x):
-        self.lines[-1].write(x)
-
-    def prettyprint(self, line):
-        self.indent = line.used
-        line.block = self
-        if not line.fits(self.width):
-            self.broken = 1
-        for l in self.lines:
-            l.prettyprint(line)
-        line.block = self.parent
-
-    def show(self, out):
-        print >> out, ('(BLOCK (width %d) (indent %d) (all %d) (broken %d)' %
-                       (self.width, self.indent, self.all, self.broken))
-        for l in self.lines:
-            l.show(out)
-        print >> out, ')'
-
-class Line:
-
-    def __init__(self, out, width):
-        self.out = out
-        self.width = width
-        self.used = 0
-        self.space = self.width
-
-    def newline(self, indent):
-        indent += self.block.indent
-        self.out.write('\n')
-        self.out.write(' ' * indent)
-        self.used = indent
-        self.space = self.width - self.used
-
-    def fits(self, n):
-        return self.space - n >= 0
-
-    def breaks(self, n):
-        return self.block.breaks(n) or not self.fits(n)
-
-    def output(self, x):
-        n = x.get_width()
-        self.space -= n
-        self.used += n
-        if self.space < 0:
-            self.space = 0
-        x.output(self.out)
-
-class PrettyPrinter:
-    """A prettyprinter based on what I remember of Derek Oppen's
-    prettyprint algorithm from TOPLAS way back.
-    """
-
-    def __init__(self, width=40):
-        self.width = width
-        self.block = None
-        self.top = None
-
-    def write(self, x):
-        self.block.add(PrettyString(x))
-
-    def add(self, item):
-        self.block.add(item)
-
-    def addbreak(self, width=1, indent=4):
-        self.add(PrettyBreak(width, indent))
-
-    def addspace(self, width=1):
-        self.add(PrettySpace(width))
-
-    def addnl(self, indent=0):
-        self.add(PrettyNewline(indent))
-
-    def begin(self, all=0):
-        block = PrettyBlock(all=all, parent=self.block)
-        self.block = block
-
-    def end(self):
-        self.block.end()
-        if self.block.parent:
-            self.block.parent.add(self.block)
-        else:
-            self.top = self.block
-        self.block = self.block.parent
-
-    def prettyprint(self, out=sys.stdout):
-        line = Line(out, self.width)
-        self.top.prettyprint(line)
-
-class SXPPrettyPrinter(PrettyPrinter):
-    """An SXP prettyprinter.
-    """
-    
-    def pstring(self, x):
-        io = StringIO.StringIO()
-        sxp.show(x, out=io)
-        io.seek(0)
-        val = io.getvalue()
-        io.close()
-        return val
-
-    def pprint(self, l):
-        if isinstance(l, types.ListType):
-            self.begin(all=1)
-            self.write('(')
-            i = 0
-            for x in l:
-                if(i): self.addbreak()
-                self.pprint(x)
-                i += 1
-            self.addbreak(width=0, indent=0)
-            self.write(')')
-            self.end()
-        else:
-            self.write(self.pstring(l))
-
-def prettyprint(sxpr, out=sys.stdout, width=80):
-    """Prettyprint an SXP form.
-
-    sxpr       s-expression
-    out                destination
-    width      maximum output width
-    """
-    if isinstance(sxpr, types.ListType):
-        pp = SXPPrettyPrinter(width=width)
-        pp.pprint(sxpr)
-        pp.prettyprint(out=out)
-    else:
-        sxp.show(sxpr, out=out)
-    print >> out
-
-def main():
-    pin = sxp.Parser()
-    while 1:
-        buf = sys.stdin.read(100)
-        pin.input(buf)
-        if buf == '': break
-    l = pin.get_val()
-    prettyprint(l, width=80)
-
-if __name__ == "__main__":
-    main()
-    
diff --git a/tools/xenmgr/lib/XendBridge.py b/tools/xenmgr/lib/XendBridge.py
deleted file mode 100644 (file)
index 10e2234..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-"""Bridge control utilities.
-"""
-import os
-import os.path
-import re
-import sys
-
-from xenmgr import XendRoot
-xroot = XendRoot.instance()
-
-os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin'
-CMD_IFCONFIG = 'ifconfig'
-CMD_ROUTE    = 'route'
-CMD_BRCTL    = 'brctl'
-CMD_IPTABLES = "iptables"
-
-DEFAULT_BRIDGE = 'nbe-br'
-DEFAULT_INTERFACE = 'eth0'
-
-opts = None
-
-class Opts:
-
-    def __init__(self, defaults):
-        for (k, v) in defaults.items():
-            setattr(self, k, v)
-        pass
-
-def cmd(p, s):
-    """Print and execute command 'p' with args 's'.
-    """
-    global opts
-    c = p + ' ' + s
-    if opts.verbose: print c
-    if not opts.dryrun:
-        os.system(c)
-
-def default_bridge():
-    return xroot.get_config_value('bridge', DEFAULT_BRIDGE)
-
-def default_interface():
-    return xroot.get_config_value('interface', DEFAULT_INTERFACE)
-
-def vif_dev(dom, vif):
-    """Return the name of the network interface for vif on domain dom.
-    """
-    return "vif%d.%d" % (dom, vif)
-
-def vif_bridge_add(dom, vif, bridge=None):
-    """Add the network interface for vif on dom to a bridge.
-    """
-    if not bridge: bridge = default_bridge()
-    d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
-    cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % d)
-    return bridge
-
-def vif_bridge_rem(dom, vif, bridge=None):
-    """Remove the network interface for vif on dom from a bridge.
-    """
-    if not bridge: bridge = default_bridge()
-    print 'vif_bridge_rem>', dom, vif, bridge
-    d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
-    cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % d)
-
-def vif_restrict_addr(dom, vif, addr, delete=0):
-    d = { 'vif': vif_dev(dom, vif), 'addr': addr}
-    if delete:
-        d['flag'] = '-D'
-    else:
-        d['flag'] = '-A'
-    cmd(CMD_IPTABLES, '-P FORWARD DROP')
-    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-in %(vif)s -s %(addr)s -j ACCEPT' % d)
-    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-out %(vif)s -d %(addr)s -j ACCEPT' % d)
-
-def bridge_create(bridge=None, **kwd):
-    """Create a bridge.
-    Defaults hello time to 0, forward delay to 0 and stp off.
-    """
-    if not bridge: bridge = default_bridge()
-    cmd(CMD_BRCTL, 'addbr %s' % bridge)
-    if kwd.get('hello', None) is None:
-        kwd['hello'] = 0
-    if kwd.get('fd', None) is None:
-        kwd['fd'] = 0
-    if kwd.get('stp', None) is None:
-        kwd['stp'] = 'off'
-    bridge_set(bridge, **kwd)
-
-def bridge_set(bridge, hello=None, fd=None, stp=None):
-    """Set bridge parameters.
-    """
-    if hello is not None:
-        cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello))
-    if fd is not None:
-        cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd))
-    if stp is not None:
-        cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp))
-
-def bridge_del(bridge=None):
-    """Delete a bridge.
-    """
-    if not bridge: bridge = default_bridge()
-    cmd(CMD_BRCTL, 'delbr %s' % bridge)
-
-def routes():
-    """Return a list of the routes.
-    """
-    fin = os.popen(CMD_ROUTE + ' -n', 'r')
-    routes = []
-    for x in fin:
-        if x.startswith('Kernel'): continue
-        if x.startswith('Destination'): continue
-        x = x.strip()
-        y = x.split()
-        z = { 'destination': y[0],
-              'gateway'    : y[1],
-              'mask'       : y[2],
-              'flags'      : y[3],
-              'metric'     : y[4],
-              'ref'        : y[5],
-              'use'        : y[6],
-              'interface'  : y[7] }
-        routes.append(z)
-    return routes
-
-def ifconfig(interface):
-    """Return the ip config for an interface,
-    """
-    fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r')
-    inetre = re.compile('\s*inet\s*addr:(?P<address>\S*)\s*Bcast:(?P<broadcast>\S*)\s*Mask:(?P<mask>\S*)')
-    info = None
-    for x in fin:
-        m = inetre.match(x)
-        if not m: continue
-        info = m.groupdict()
-        info['interface'] = interface
-        break
-    return info
-
-def reconfigure(interface=None, bridge=None):
-    """Reconfigure an interface to be attached to a bridge, and give the bridge
-    the IP address etc. from interface. Move the default route to the interface
-    to the bridge.
-
-    If opts.create is true, creates the bridge.
-    """
-    global opts
-    if not interface: interface = default_interface()
-    if not bridge: bridge = default_bridge()
-    intf_info = ifconfig(interface)
-    if not intf_info:
-        print 'Interface not found:', interface
-        return
-    if opts.create:
-        bridge_create(bridge)
-    #bridge_info = ifconfig(bridge)
-    #if not bridge_info:
-    #    print 'Bridge not found:', bridge
-    #    return
-    route_info = routes()
-    intf_info['bridge'] = bridge
-    intf_info['gateway'] = None
-    for r in route_info:
-        if (r['destination'] == '0.0.0.0' and
-            'G' in r['flags'] and
-            r['interface'] == interface):
-            intf_info['gateway'] = r['gateway']
-    if not intf_info['gateway']:
-        print 'Gateway not found: ', interface
-        return
-    cmd(CMD_IFCONFIG,
-        '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up'
-        % intf_info)
-    cmd(CMD_ROUTE,
-        'add default gateway %(gateway)s dev %(bridge)s'
-        % intf_info)
-    cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info)
-    cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info)
-
-defaults = {
-    'interface': default_interface(),
-    'bridge'   : default_bridge(),
-    'verbose'  : 1,
-    'dryrun'   : 0,
-    'create'   : 0,
-    }
-
-opts = Opts(defaults)
-
-def set_opts(val):
-    global opts
-    opts = val
-    return opts
diff --git a/tools/xenmgr/lib/XendClient.py b/tools/xenmgr/lib/XendClient.py
deleted file mode 100644 (file)
index 664835a..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Client API for the HTTP interface on xend.
-Callable as a script - see main().
-"""
-import sys
-import httplib
-import types
-from StringIO import StringIO
-import urlparse
-
-from encode import *
-import sxp
-import PrettyPrint
-
-DEBUG = 0
-
-class Foo(httplib.HTTPResponse):
-
-    def begin(self):
-        fin = self.fp
-        while(1):
-            buf = fin.readline()
-            print "***", buf
-            if buf == '':
-                print
-                sys.exit()
-
-
-def sxprio(sxpr):
-    io = StringIO()
-    sxp.show(sxpr, out=io)
-    print >> io
-    io.seek(0)
-    return io
-
-def fileof(val):
-    """Converter for passing configs.
-    Handles lists, files directly.
-    Assumes a string is a file name and passes its contents.
-    """
-    if isinstance(val, types.ListType):
-        return sxprio(val)
-    if isinstance(val, types.StringType):
-        return file(val)
-    if hasattr(val, 'readlines'):
-        return val
-
-# todo: need to sort of what urls/paths are using for objects.
-# e.g. for domains at the moment return '0'.
-# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
-# As an arg, assume abs path is obj uri, otherwise just id.
-
-# Function to convert to full url: Xend.uri(path), e.g.
-# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
-# And should accept urls for ids?
-
-def urljoin(location, root, prefix='', rest=''):
-    prefix = str(prefix)
-    rest = str(rest)
-    base = 'http://' + location + root + prefix
-    url = urlparse.urljoin(base, rest)
-    return url
-
-def nodeurl(location, root, id=''):
-    return urljoin(location, root, 'node/', id)
-
-def domainurl(location, root, id=''):
-    return urljoin(location, root, 'domain/', id)
-
-def consoleurl(location, root, id=''):
-    return urljoin(location, root, 'console/', id)
-
-def deviceurl(location, root, id=''):
-    return urljoin(location, root, 'device/', id)
-
-def vneturl(location, root, id=''):
-    return urljoin(location, root, 'vnet/', id)
-
-def eventurl(location, root, id=''):
-    return urljoin(location, root, 'event/', id)
-
-def xend_request(url, method, data=None):
-    urlinfo = urlparse.urlparse(url)
-    (uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo
-    if DEBUG: print url, urlinfo
-    if uproto != 'http':
-        raise StandardError('Invalid protocol: ' + uproto)
-    if DEBUG: print '>xend_request', ulocation, upath, method, data
-    (hdr, args) = encode_data(data)
-    if data and method == 'GET':
-        upath += '?' + args
-        args = None
-    if method == "POST" and upath.endswith('/'):
-        upath = upath[:-1]
-    if DEBUG: print "ulocation=", ulocation, "upath=", upath, "args=", args
-    #hdr['User-Agent'] = 'Mozilla'
-    #hdr['Accept'] = 'text/html,text/plain'
-    conn = httplib.HTTPConnection(ulocation)
-    #conn.response_class = Foo
-    if DEBUG: conn.set_debuglevel(1)
-    conn.request(method, upath, args, hdr)
-    resp = conn.getresponse()
-    if DEBUG: print resp.status, resp.reason
-    if DEBUG: print resp.msg.headers
-    if resp.status in [204, 404]:
-        return None
-    if resp.status not in [200, 201, 202, 203]:
-        raise RuntimeError(resp.reason)
-    pin = sxp.Parser()
-    data = resp.read()
-    if DEBUG: print "***data" , data
-    if DEBUG: print "***"
-    pin.input(data);
-    pin.input_eof()
-    conn.close()
-    val = pin.get_val()
-    #if isinstance(val, types.ListType) and sxp.name(val) == 'val':
-    #    val = val[1]
-    if isinstance(val, types.ListType) and sxp.name(val) == 'err':
-        raise RuntimeError(val[1])
-    if DEBUG: print '**val='; sxp.show(val); print
-    return val
-
-def xend_get(url, args=None):
-    return xend_request(url, "GET", args)
-
-def xend_call(url, data):
-    return xend_request(url, "POST", data)
-
-class Xend:
-
-    SRV_DEFAULT = "localhost:8000"
-    ROOT_DEFAULT = "/xend/"
-
-    def __init__(self, srv=None, root=None):
-        self.bind(srv, root)
-
-    def bind(self, srv=None, root=None):
-        if srv is None: srv = self.SRV_DEFAULT
-        if root is None: root = self.ROOT_DEFAULT
-        if not root.endswith('/'): root += '/'
-        self.location = srv
-        self.root = root
-
-    def nodeurl(self, id=''):
-        return nodeurl(self.location, self.root, id)
-
-    def domainurl(self, id=''):
-        return domainurl(self.location, self.root, id)
-
-    def consoleurl(self, id=''):
-        return consoleurl(self.location, self.root, id)
-
-    def deviceurl(self, id=''):
-        return deviceurl(self.location, self.root, id)
-
-    def vneturl(self, id=''):
-        return vneturl(self.location, self.root, id)
-
-    def eventurl(self, id=''):
-        return eventurl(self.location, self.root, id)
-
-    def xend(self):
-        return xend_get(urljoin(self.location, self.root))
-
-    def xend_node(self):
-        return xend_get(self.nodeurl())
-
-    def xend_node_cpu_rrobin_slice_set(self, slice):
-        return xend_call(self.nodeurl(),
-                         {'op'      : 'cpu_rrobin_slice_set',
-                          'slice'   : slice })
-    
-    def xend_node_cpu_bvt_slice_set(self, slice):
-        return xend_call(self.nodeurl(),
-                         {'op'      : 'cpu_bvt_slice_set',
-                          'slice'   : slice })
-
-    def xend_domains(self):
-        return xend_get(self.domainurl())
-
-    def xend_domain_create(self, conf):
-        return xend_call(self.domainurl(),
-                         {'op'      : 'create',
-                          'config'  : fileof(conf) })
-
-    def xend_domain(self, id):
-        return xend_get(self.domainurl(id))
-
-    def xend_domain_unpause(self, id):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'unpause'})
-
-    def xend_domain_pause(self, id):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'pause'})
-
-    def xend_domain_shutdown(self, id):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'shutdown'})
-
-    def xend_domain_destroy(self, id):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'destroy'})
-
-    def xend_domain_save(self, id, filename):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'save',
-                          'file'    : filename})
-
-    def xend_domain_restore(self, id, filename, conf):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'restore',
-                          'file'    : filename,
-                          'config'  : fileof(conf) })
-
-    def xend_domain_migrate(self, id, dst):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'migrate',
-                          'dst'     : dst})
-
-    def xend_domain_pincpu(self, id, cpu):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'pincpu',
-                          'cpu'     : cpu})
-
-    def xend_domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'cpu_bvt_set',
-                          'mcuadv'  : mvuadv,
-                          'warp'    : warp,
-                          'warpl'   : warpl,
-                          'warpu'   : warpu })
-
-    def xend_domain_cpu_atropos_set(self, id, period, slice, latency, xtratime):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'cpu_atropos_set',
-                          'period'  : period,
-                          'slice'   : slice,
-                          'latency' : latency,
-                          'xtratime': xtratime })
-
-    def xend_domain_vifs(self, id):
-        return xend_get(self.domainurl(id),
-                        { 'op'      : 'vifs' })
-    
-    def xend_domain_vif_ip_add(self, id, vif, ipaddr):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'vif_ip_add',
-                          'vif'     : vif,
-                          'ip'      : ipaddr })
-        
-    def xend_domain_vbds(self, id):
-        return xend_get(self.domainurl(id),
-                        {'op'       : 'vbds'})
-
-    def xend_domain_vbd(self, id, vbd):
-        return xend_get(self.domainurl(id),
-                        {'op'       : 'vbd',
-                         'vbd'      : vbd})
-
-    def xend_consoles(self):
-        return xend_get(self.consoleurl())
-
-    def xend_console(self, id):
-        return xend_get(self.consoleurl(id))
-
-    def xend_vnets(self):
-        return xend_get(self.vneturl())
-
-    def xend_vnet_create(self, conf):
-        return xend_call(self.vneturl(),
-                         {'op': 'create', 'config': fileof(conf) })
-
-    def xend_vnet(self, id):
-        return xend_get(self.vneturl(id))
-
-    def xend_vnet_delete(self, id):
-        return xend_call(self.vneturl(id),
-                         {'op': 'delete'})
-
-    def xend_event_inject(self, sxpr):
-        val = xend_call(self.eventurl(),
-                        {'op': 'inject', 'event': fileof(sxpr) })
-    
-
-def main(argv):
-    """Call an API function:
-    
-    python XendClient.py fn args...
-
-    The leading 'xend_' on the function can be omitted.
-    Example:
-
-    > python XendClient.py domains
-    (domain 0 8)
-    > python XendClient.py domain 0
-    (domain (id 0) (name Domain-0) (memory 128))
-    """
-    server = Xend()
-    fn = argv[1]
-    if not fn.startswith('xend'):
-        fn = 'xend_' + fn
-    args = argv[2:]
-    val = getattr(server, fn)(*args)
-    PrettyPrint.prettyprint(val)
-    print
-
-if __name__ == "__main__":
-    main(sys.argv)
-else:    
-    server = Xend()
diff --git a/tools/xenmgr/lib/XendConsole.py b/tools/xenmgr/lib/XendConsole.py
deleted file mode 100644 (file)
index dcf992d..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-import socket
-import Xc
-xc = Xc.new()
-
-import sxp
-import XendRoot
-xroot = XendRoot.instance()
-import XendDB
-
-import EventServer
-eserver = EventServer.instance()
-
-from xenmgr.server import SrvConsoleServer
-xcd = SrvConsoleServer.instance()
-
-class XendConsoleInfo:
-    """Console information record.
-    """
-
-    def __init__(self, console, dom1, port1, dom2, port2, conn=None):
-        self.console = console
-        self.dom1  = int(dom1)
-        self.port1 = int(port1)
-        self.dom2  = int(dom2)
-        self.port2 = int(port2)
-        self.conn  = conn
-        #self.id = "%d.%d-%d.%d" % (self.dom1, self.port1, self.dom2, self.port2)
-        self.id = str(port1)
-
-    def __str__(self):
-        s = "console"
-        s += " id=%s" % self.id
-        s += " src=%d.%d" % (self.dom1, self.port1)
-        s += " dst=%d.%d" % (self.dom2, self.port2)
-        s += " port=%s" % self.console
-        if self.conn:
-            s += " conn=%s:%s" % (self.conn[0], self.conn[1])
-        return s
-
-    def sxpr(self):
-        sxpr = ['console',
-                ['id', self.id],
-                ['src', self.dom1, self.port1],
-                ['dst', self.dom2, self.port2],
-                ['port', self.console],
-                ]
-        if self.conn:
-            sxpr.append(['connected', self.conn[0], self.conn[1]])
-        return sxpr
-
-    def connection(self):
-        return self.conn
-
-    def update(self, consinfo):
-        conn = sxp.child(consinfo, 'connected')
-        if conn:
-            self.conn = conn[1:]
-        else:
-            self.conn = None
-
-    def uri(self):
-        """Get the uri to use to connect to the console.
-        This will be a telnet: uri.
-
-        return uri
-        """
-        host = socket.gethostname()
-        return "telnet://%s:%s" % (host, self.console)
-
-class XendConsole:
-
-    dbpath = "console"
-
-    def  __init__(self):
-        self.db = XendDB.XendDB(self.dbpath)
-        self.console = {}
-        self.console_db = self.db.fetchall("")
-        if xroot.get_rebooted():
-            print 'XendConsole> rebooted: removing all console info'
-            self.rm_all()
-        eserver.subscribe('xend.domain.died', self.onDomainDied)
-        eserver.subscribe('xend.domain.destroy', self.onDomainDied)
-
-    def rm_all(self):
-        """Remove all console info. Used after reboot.
-        """
-        for (k, v) in self.console_db.items():
-            self._delete_console(k)
-
-    def refresh(self):
-        consoles = xcd.consoles()
-        cons = {}
-        for consinfo in consoles:
-            id = str(sxp.child_value(consinfo, 'id'))
-            cons[id] = consinfo
-            if id not in self.console:
-                self._new_console(consinfo)
-        for c in self.console.values():
-            consinfo = cons.get(c.id)
-            if consinfo:
-                c.update(consinfo)
-            else:
-                self._delete_console(c.id)
-
-    def onDomainDied(self, event, val):
-        dom = int(val)
-        #print 'XendConsole>onDomainDied', 'event', event, "dom=", dom
-        for c in self.consoles():
-            #print 'onDomainDied', "dom=", dom, "dom1=", c.dom1, "dom2=", c.dom2
-            if (c.dom1 == dom) or (c.dom2 == dom):
-                'XendConsole>onDomainDied', 'delete console dom=', dom
-                ctrl = xcd.get_domain_console(dom)
-                if ctrl:
-                    ctrl.close()
-                self._delete_console(c.id)
-
-    def sync(self):
-        self.db.saveall("", self.console_db)
-
-    def sync_console(self, id):
-        self.db.save(id, self.console_db[id])
-
-    def _new_console(self, consinfo):
-        # todo: xen needs a call to get current domain id.
-        dom1 = 0
-        port1 = sxp.child_value(consinfo, 'local_port')
-        dom2 = sxp.child_value(consinfo, 'domain')
-        port2 = sxp.child_value(consinfo, 'remote_port')
-        console = sxp.child_value(consinfo, 'console_port')
-        info = XendConsoleInfo(console, dom1, int(port1), int(dom2), int(port2))
-        info.update(consinfo)
-        self._add_console(info.id, info)
-        return info
-
-    def _add_console(self, id, info):
-        self.console[id] = info
-        self.console_db[id] = info.sxpr()
-        self.sync_console(id)
-
-    def _delete_console(self, id):
-        if id in self.console:
-            del self.console[id]
-        if id in self.console_db:
-            del self.console_db[id]
-            self.db.delete(id)
-
-    def console_ls(self):
-        self.refresh()
-        return self.console.keys()
-
-    def consoles(self):
-        self.refresh()
-        return self.console.values()
-    
-    def console_create(self, dom):
-        consinfo = xcd.console_create(dom)
-        info = self._new_console(consinfo)
-        return info
-    
-    def console_get(self, id):
-        self.refresh()
-        return self.console.get(id)
-
-    def console_delete(self, id):
-        self._delete_console(id)
-
-    def console_disconnect(self, id):
-        id = int(id)
-        xcd.console_disconnect(id)
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendConsole()
-    return inst
diff --git a/tools/xenmgr/lib/XendDB.py b/tools/xenmgr/lib/XendDB.py
deleted file mode 100644 (file)
index 6a27e65..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-import os
-import os.path
-import errno
-import dircache
-import time
-
-import sxp
-import XendRoot
-xroot = XendRoot.instance()
-
-class XendDB:
-    """Persistence for Xend. Stores data in files and directories.
-    """
-
-    def __init__(self, path=None):
-        self.dbpath = xroot.get_dbroot()
-        if path:
-            self.dbpath = os.path.join(self.dbpath, path)
-        pass
-
-    def filepath(self, path):
-        return os.path.join(self.dbpath, path)
-        
-    def fetch(self, path):
-        fpath = self.filepath(path)
-        return self.fetchfile(fpath)
-
-    def fetchfile(self, fpath):
-        pin = sxp.Parser()
-        fin = file(fpath, "rb")
-        try:
-            while 1:
-                try:
-                    buf = fin.read(1024)
-                except IOError, ex:
-                    if ex.errno == errno.EINTR:
-                        continue
-                    else:
-                        raise
-                pin.input(buf)
-                if buf == '':
-                    pin.input_eof()
-                    break
-        finally:
-            fin.close()
-        return pin.get_val()
-
-    def save(self, path, sxpr):
-        fpath = self.filepath(path)
-        return self.savefile(fpath, sxpr)
-    
-    def savefile(self, fpath, sxpr):
-        fdir = os.path.dirname(fpath)
-        if not os.path.isdir(fdir):
-            os.makedirs(fdir)
-        fout = file(fpath, "wb+")
-        try:
-            t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
-            fout.write("# %s %s\n" % (fpath, t))
-            sxp.show(sxpr, out=fout)
-        finally:
-            fout.close()
-
-    def fetchall(self, path):
-        dpath = self.filepath(path)
-        d = {}
-        for k in dircache.listdir(dpath):
-            try:
-                v = self.fetchfile(os.path.join(dpath, k))
-                d[k] = v
-            except:
-                pass
-        return d
-
-    def saveall(self, path, d):
-        for (k, v) in d.items():
-            self.save(os.path.join(path, k), v)
-
-    def delete(self, path):
-        dpath = self.filepath(path)
-        os.unlink(dpath)
-
-    def ls(self, path):
-        dpath = self.filepath(path)
-        return dircache.listdir(dpath)
-            
-        
-
-        
diff --git a/tools/xenmgr/lib/XendDomain.py b/tools/xenmgr/lib/XendDomain.py
deleted file mode 100644 (file)
index 2eaa9b6..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Handler for domain operations.
- Nothing here is persistent (across reboots).
- Needs to be persistent for one uptime.
-"""
-import sys
-
-from twisted.internet import defer
-
-import Xc; xc = Xc.new()
-import xenctl.ip
-
-import sxp
-import XendRoot
-xroot = XendRoot.instance()
-import XendDB
-import XendDomainInfo
-import XendConsole
-import EventServer
-
-from xenmgr.server import SrvConsoleServer
-xend = SrvConsoleServer.instance()
-
-eserver = EventServer.instance()
-
-__all__ = [ "XendDomain" ]
-        
-class XendDomain:
-    """Index of all domains. Singleton.
-    """
-    
-    dbpath = "domain"
-    domain = {}
-    
-    def __init__(self):
-        self.xconsole = XendConsole.instance()
-        # Table of domain info indexed by domain id.
-        self.db = XendDB.XendDB(self.dbpath)
-        #self.domain = {}
-        self.domain_db = self.db.fetchall("")
-        if xroot.get_rebooted():
-            print 'XendDomain> rebooted: removing all domain info'
-            self.rm_all()
-        eserver.subscribe('xend.virq', self.onVirq)
-        self.initial_refresh()
-
-    def onVirq(self, event, val):
-        print 'XendDomain> virq', val
-        self.reap()
-
-    def rm_all(self):
-        """Remove all domain info. Used after reboot.
-        """
-        for (k, v) in self.domain_db.items():
-            self._delete_domain(k, notify=0)
-            
-    def initial_refresh(self):
-        """Refresh initial domain info from domain_db.
-        """
-        print "initial_refresh>"
-        for d in self.domain_db.values(): print 'db dom=', d
-        domlist = xc.domain_getinfo()
-        for d in domlist: print 'xc dom=', d
-        doms = {}
-        for d in domlist:
-            domid = str(d['dom'])
-            doms[domid] = d
-        dlist = []
-        for config in self.domain_db.values():
-            domid = str(sxp.child_value(config, 'id'))
-            print "dom=", domid, "config=", config
-            if domid in doms:
-                print "dom=", domid, "new"
-                deferred = self._new_domain(config, doms[domid])
-                dlist.append(deferred)
-            else:
-                print "dom=", domid, "del"
-                self._delete_domain(domid)
-        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
-        def cbok(val):
-            #print "doms:"
-            #for d in self.domain.values(): print 'dom', d
-            self.refresh()
-            print "XendDomain>initial_refresh> doms:"
-            for d in self.domain.values(): print 'dom', d
-        deferred.addCallback(cbok)
-
-    def sync(self):
-        """Sync domain db to disk.
-        """
-        self.db.saveall("", self.domain_db)
-
-    def sync_domain(self, dom):
-        """Sync info for a domain to disk.
-
-        dom    domain id (string)
-        """
-        self.db.save(dom, self.domain_db[dom])
-
-    def close(self):
-        pass
-
-    def _new_domain(self, savedinfo, info):
-        """Create a domain entry from saved info.
-        """
-##         console = None
-##         kernel = None
-##         id = sxp.child_value(info, 'id')
-##         dom = int(id)
-##         name = sxp.child_value(info, 'name')
-##         memory = int(sxp.child_value(info, 'memory'))
-##         consoleinfo = sxp.child(info, 'console')
-##         if consoleinfo:
-##             consoleid = sxp.child_value(consoleinfo, 'id')
-##             console = self.xconsole.console_get(consoleid)
-##         if dom and console is None:
-##             # Try to connect a console.
-##             console = self.xconsole.console_create(dom)
-##         config = sxp.child(info, 'config')
-##         if config:
-##             image = sxp.child(info, 'image')
-##             if image:
-##                 image = sxp.child0(image)
-##                 kernel = sxp.child_value(image, 'kernel')
-##         dominfo = XendDomainInfo.XendDomainInfo(
-##             config, dom, name, memory, kernel, console)
-        config = sxp.child_value(savedinfo, 'config')
-        deferred = XendDomainInfo.vm_recreate(config, info)
-        def fn(dominfo):
-            self.domain[dominfo.id] = dominfo
-        deferred.addCallback(fn)
-        return deferred
-
-    def _add_domain(self, id, info, notify=1):
-        self.domain[id] = info
-        self.domain_db[id] = info.sxpr()
-        self.sync_domain(id)
-        if notify: eserver.inject('xend.domain.created', id)
-
-    def _delete_domain(self, id, notify=1):
-        if id in self.domain:
-            if notify: eserver.inject('xend.domain.died', id)
-            del self.domain[id]
-        if id in self.domain_db:
-            del self.domain_db[id]
-            self.db.delete(id)
-
-    def reap(self):
-        """Go through the domains looking for ones that have crashed or stopped.
-        Tidy them up.
-        """
-        print 'XendDomain>reap>'
-        domlist = xc.domain_getinfo()
-        casualties = []
-        for d in domlist:
-            #print 'dom', d
-            dead = 0
-            dead = dead or (d['crashed'] or d['shutdown'])
-            dead = dead or (d['dying'] and
-                            not(d['running'] or d['paused'] or d['blocked']))
-            if dead:
-                casualties.append(d)
-        for d in casualties:
-            id = str(d['dom'])
-            print 'XendDomain>reap> died id=', id, d
-            dominfo = self.domain.get(id)
-            if not dominfo: continue
-            dominfo.died()
-            self.domain_destroy(id, refresh=0)
-        print 'XendDomain>reap<'
-
-    def refresh(self):
-        """Refresh domain list from Xen.
-        """
-        domlist = xc.domain_getinfo()
-        # Index the domlist by id.
-        # Add entries for any domains we don't know about.
-        doms = {}
-        for d in domlist:
-            id = str(d['dom'])
-            doms[id] = d
-            if id not in self.domain:
-                config = None
-                #image = None
-                #newinfo = XendDomainInfo.XendDomainInfo(
-                #    config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d)
-                deferred = XendDomainInfo.vm_recreate(config, d)
-                def fn(dominfo):
-                    self._add_domain(dominfo.id, dominfo)
-                deferred.addCallback(fn)
-        # Remove entries for domains that no longer exist.
-        for d in self.domain.values():
-            dominfo = doms.get(d.id)
-            if dominfo:
-                d.update(dominfo)
-            else:
-                self._delete_domain(d.id)
-        self.reap()
-
-    def refresh_domain(self, id):
-        dom = int(id)
-        dominfo = xc.domain_getinfo(dom, 1)
-        if dominfo == [] or dominfo[0]['dom'] != dom:
-            try:
-                self._delete_domain(id)
-            except:
-                print 'refresh_domain: error'
-                raise
-                pass
-        else:
-            d = self.domain.get(id)
-            if d:
-                d.update(dominfo[0])
-
-    def domain_ls(self):
-        # List domains.
-        # Update info from kernel first.
-        self.refresh()
-        return self.domain.keys()
-
-    def domains(self):
-        self.refresh()
-        return self.domain.values()
-    
-    def domain_create(self, config):
-        # Create domain, log it.
-        deferred = XendDomainInfo.vm_create(config)
-        def fn(dominfo):
-            self._add_domain(dominfo.id, dominfo)
-            return dominfo
-        deferred.addCallback(fn)
-        return deferred
-    
-    def domain_get(self, id):
-        id = str(id)
-        self.refresh_domain(id)
-        return self.domain[id]
-    
-    def domain_unpause(self, id):
-        """(Re)start domain running.
-        """
-        dom = int(id)
-        eserver.inject('xend.domain.unpause', id)
-        return xc.domain_unpause(dom=dom)
-    
-    def domain_pause(self, id):
-        """Pause domain execution.
-        """
-        dom = int(id)
-        eserver.inject('xend.domain.pause', id)
-        return xc.domain_pause(dom=dom)
-    
-    def domain_shutdown(self, id, reason='poweroff'):
-        """Shutdown domain (nicely).
-        """
-        dom = int(id)
-        if dom <= 0:
-            return 0
-        eserver.inject('xend.domain.shutdown', [id, reason])
-        val = xend.domain_shutdown(dom, reason)
-        self.refresh()
-        return val
-    
-    def domain_destroy(self, id, refresh=1):
-        """Terminate domain immediately.
-        """
-        dom = int(id)
-        if dom <= 0:
-            return 0
-        eserver.inject('xend.domain.destroy', id)
-        val = xc.domain_destroy(dom=dom)
-        if refresh: self.refresh()
-        return val       
-
-    def domain_migrate(self, id, dst):
-        """Start domain migration.
-        """
-        # Need a cancel too?
-        pass
-    
-    def domain_save(self, id, dst, progress=0):
-        """Save domain state to file, destroy domain.
-        """
-        dom = int(id)
-        self.domain_pause(id)
-        eserver.inject('xend.domain.save', id)
-        rc = xc.linux_save(dom=dom, state_file=dst, progress=progress)
-        if rc == 0:
-            self.domain_destroy(id)
-        return rc
-    
-    def domain_restore(self, src, config, progress=0):
-        """Restore domain from file.
-        """
-        dominfo = XendDomainInfo.dom_restore(dom, config)
-        self._add_domain(dominfo.id, dominfo)
-        return dominfo
-    
-    #============================================================================
-    # Backward compatibility stuff from here on.
-
-    def domain_pincpu(self, dom, cpu):
-        dom = int(dom)
-        return xc.domain_pincpu(dom, cpu)
-
-    def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
-        dom = int(dom)
-        return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
-                                      warp=warp, warpl=warpl, warpu=warpu)
-
-    def domain_cpu_bvt_get(self, dom):
-        dom = int(dom)
-        return xc.bvtsched_domain_get(dom)
-    
-    def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
-        dom = int(dom)
-        return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
-
-    def domain_cpu_atropos_get(self, dom):
-        dom = int(dom)
-        return xc.atropos_domain_get(dom)
-
-    def domain_vif_ls(self, dom):
-        dominfo = self.domain_get(dom)
-        if not dominfo: return None
-        devs = dominfo.get_devices('vif')
-        return range(0, len(devs))
-
-    def domain_vif_get(self, dom, vif):
-        dominfo = self.domain_get(dom)
-        if not dominfo: return None
-        return dominfo.get_device_by_index(vif)
-
-    def domain_vif_ip_add(self, dom, vif, ip):
-        dom = int(dom)
-        return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
-
-    def domain_vbd_ls(self, dom):
-        dominfo = self.domain_get(dom)
-        if not dominfo: return []
-        devs = dominfo.get_devices('vbd')
-        return [ sxp.child_value(v, 'dev') for v in devs ]
-
-    def domain_vbd_get(self, dom, vbd):
-        dominfo = self.domain_get(dom)
-        if not dominfo: return None
-        devs = dominfo.get_devices('vbd')
-        for v in devs:
-            if sxp.child_value(v, 'dev') == vbd:
-                return v
-        return None
-
-    def domain_shadow_control(self, dom, op):
-        dom = int(dom)
-        return xc.shadow_control(dom, op)
-
-    #============================================================================
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendDomain()
-    return inst
diff --git a/tools/xenmgr/lib/XendDomainConfig.py b/tools/xenmgr/lib/XendDomainConfig.py
deleted file mode 100644 (file)
index 35db31f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Handler for persistent domain configs.
-
-"""
-
-import sxp
-import XendDB
-import XendDomain
-
-__all__ = [ "XendDomainConfig" ]
-
-class XendDomainConfig:
-
-    dbpath = 'config'
-
-    def __init__(self):
-        self.db = XendDB.XendDB(self.dbpath)
-
-    def domain_config_ls(self, path):
-        return self.db.ls(path)
-
-    def domain_config_create(self, path, sxpr):
-        self.db.save(path, sxpr)
-        pass
-
-    def domain_config_delete(self, path):
-        self.db.delete(path)
-
-    def domain_config_instance(self, path):
-        """Create a domain from a config.
-        """
-        config = self.db.fetch(path)
-        xd = XendDomain.instance()
-        newdom = xd.domain_create(config)
-        return newdom
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendDomainConfig()
-    return inst
diff --git a/tools/xenmgr/lib/XendDomainInfo.py b/tools/xenmgr/lib/XendDomainInfo.py
deleted file mode 100644 (file)
index 1f44f02..0000000
+++ /dev/null
@@ -1,911 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Representation of a single domain.
-Includes support for domain construction, using
-open-ended configurations.
-
-Author: Mike Wray <mike.wray@hpl.hp.com>
-
-"""
-
-import string
-import re
-import sys
-import os
-
-from twisted.internet import defer
-
-import Xc; xc = Xc.new()
-import xenctl.ip
-
-import sxp
-
-import XendConsole
-xendConsole = XendConsole.instance()
-
-import XendBridge
-
-import server.SrvConsoleServer
-xend = server.SrvConsoleServer.instance()
-
-SIF_BLK_BE_DOMAIN = (1<<4)
-SIF_NET_BE_DOMAIN = (1<<5)
-
-def readlines(fd):
-    """Version of readlines safe against EINTR.
-    """
-    import errno
-    
-    lines = []
-    while 1:
-        try:
-            line = fd.readline()
-        except IOError, ex:
-            if ex.errno == errno.EINTR:
-                continue
-            else:
-                raise
-        if line == '': break
-        lines.append(line)
-    return lines
-
-class VmError(ValueError):
-    """Vm construction error."""
-
-    def __init__(self, value):
-        self.value = value
-
-    def __str__(self):
-        return self.value
-
-
-def blkdev_name_to_number(name):
-    """Take the given textual block-device name (e.g., '/dev/sda1',
-    'hda') and return the device number used by the OS. """
-
-    if not re.match( '/dev/', name ):
-        name = '/dev/' + name
-        
-    return os.stat(name).st_rdev
-
-def lookup_raw_partn(partition):
-    """Take the given block-device name (e.g., '/dev/sda1', 'hda')
-    and return a dictionary { device, start_sector,
-    nr_sectors, type }
-        device:       Device number of the given partition
-        start_sector: Index of first sector of the partition
-        nr_sectors:   Number of sectors comprising this partition
-        type:         'Disk' or identifying name for partition type
-    """
-
-    if not re.match( '/dev/', partition ):
-        partition = '/dev/' + partition
-
-    drive = re.split( '[0-9]', partition )[0]
-
-    if drive == partition:
-        fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
-        line = readline(fd)
-        if line:
-            return [ { 'device' : blkdev_name_to_number(drive),
-                       'start_sector' : long(0),
-                       'nr_sectors' : long(line) * 2,
-                       'type' : 'Disk' } ]
-        return None
-
-    # determine position on disk
-    fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
-
-    #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
-    lines = readlines(fd)
-    for line in lines:
-        m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
-                       'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
-        if m:
-            return [ { 'device' : blkdev_name_to_number(drive),
-                       'start_sector' : long(m.group(1)),
-                       'nr_sectors' : long(m.group(2)),
-                       'type' : m.group(3) } ]
-    
-    return None
-
-def lookup_disk_uname(uname):
-    """Lookup a list of segments for a physical device.
-    uname [string]:  name of the device in the format \'phy:dev\' for a physical device
-    returns [list of dicts]: list of extents that make up the named device
-    """
-    ( type, d_name ) = string.split( uname, ':' )
-
-    if type == "phy":
-        segments = lookup_raw_partn( d_name )
-    else:
-        segments = None
-    return segments
-
-def make_disk(dom, uname, dev, mode, recreate=0):
-    """Create a virtual disk device for a domain.
-
-    @returns Deferred
-    """
-    segments = lookup_disk_uname(uname)
-    if not segments:
-        raise VmError("vbd: Segments not found: uname=%s" % uname)
-    if len(segments) > 1:
-        raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname)
-    segment = segments[0]
-    vdev = blkdev_name_to_number(dev)
-    ctrl = xend.blkif_create(dom, recreate=recreate)
-    
-    def fn(ctrl):
-        return xend.blkif_dev_create(dom, vdev, mode, segment, recreate=recreate)
-    ctrl.addCallback(fn)
-    return ctrl
-        
-def make_vif(dom, vif, vmac, recreate=0):
-    """Create a virtual network device for a domain.
-
-    
-    @returns Deferred
-    """
-    xend.netif_create(dom, recreate=recreate)
-    d = xend.netif_dev_create(dom, vif, vmac, recreate=recreate)
-    return d
-
-def vif_up(iplist):
-    """send an unsolicited ARP reply for all non link-local IP addresses.
-
-    iplist IP addresses
-    """
-
-    IP_NONLOCAL_BIND = '/proc/sys/net/ipv4/ip_nonlocal_bind'
-    
-    def get_ip_nonlocal_bind():
-        return int(open(IP_NONLOCAL_BIND, 'r').read()[0])
-
-    def set_ip_nonlocal_bind(v):
-        print >> open(IP_NONLOCAL_BIND, 'w'), str(v)
-
-    def link_local(ip):
-        return xenctl.ip.check_subnet(ip, '169.254.0.0', '255.255.0.0')
-
-    def arping(ip, gw):
-        cmd = '/usr/sbin/arping -A -b -I eth0 -c 1 -s %s %s' % (ip, gw)
-        print cmd
-        os.system(cmd)
-        
-    gateway = xenctl.ip.get_current_ipgw() or '255.255.255.255'
-    nlb = get_ip_nonlocal_bind()
-    if not nlb: set_ip_nonlocal_bind(1)
-    try:
-        for ip in iplist:
-            if not link_local(ip):
-                arping(ip, gateway)
-    finally:
-        if not nlb: set_ip_nonlocal_bind(0)
-
-config_handlers = {}
-
-def add_config_handler(name, h):
-    """Add a handler for a config field.
-
-    name     field name
-    h        handler: fn(vm, config, field, index)
-    """
-    config_handlers[name] = h
-
-def get_config_handler(name):
-    """Get a handler for a config field.
-
-    returns handler or None
-    """
-    return config_handlers.get(name)
-
-"""Table of handlers for virtual machine images.
-Indexed by image type.
-"""
-image_handlers = {}
-
-def add_image_handler(name, h):
-    """Add a handler for an image type
-    name     image type
-    h        handler: fn(config, name, memory, image)
-    """
-    image_handlers[name] = h
-
-def get_image_handler(name):
-    """Get the handler for an image type.
-    name     image type
-
-    returns handler or None
-    """
-    return image_handlers.get(name)
-
-"""Table of handlers for devices.
-Indexed by device type.
-"""
-device_handlers = {}
-
-def add_device_handler(name, h):
-    """Add a handler for a device type.
-
-    name      device type
-    h         handler: fn(vm, dev)
-    """
-    device_handlers[name] = h
-
-def get_device_handler(name):
-    """Get the handler for a device type.
-
-    name      device type
-
-    returns handler or None
-    """
-    return device_handlers.get(name)
-
-def vm_create(config):
-    """Create a VM from a configuration.
-    If a vm has been partially created and there is an error it
-    is destroyed.
-
-    config    configuration
-
-    returns Deferred
-    raises VmError for invalid configuration
-    """
-    print 'vm_create>'
-    vm = XendDomainInfo()
-    return vm.construct(config)
-
-def vm_recreate(config, info):
-    """Create the VM object for an existing domain.
-    """
-    vm = XendDomainInfo()
-    vm.recreate = 1
-    vm.setdom(info['dom'])
-    vm.name = info['name']
-    vm.memory = info['mem_kb']/1024
-    if config:
-        d = vm.construct(config)
-    else:
-        d = defer.Deferred()
-        d.callback(vm)
-    return d
-
-def vm_restore(src, config, progress=0):
-    """Restore a VM from a disk image.
-
-    src      saved state to restore
-    config   configuration
-    progress progress reporting flag
-    returns  deferred
-    raises   VmError for invalid configuration
-    """
-    vm = XendDomainInfo()
-    vm.config = config
-    ostype = "linux" #todo set from config
-    restorefn = getattr(xc, "%s_restore" % ostype)
-    dom = restorefn(state_file=src, progress=progress)
-    if dom < 0:
-        raise VMError('restore failed')
-    deferred = vm.dom_configure(dom)
-    def vifs_cb(val, vm):
-        vif_up(vm.ipaddrs)
-    deferred.addCallback(vifs_cb, vm)
-    return deferred
-    
-def dom_get(dom):
-    domlist = xc.domain_getinfo(dom=dom)
-    if domlist and dom == domlist[0]['dom']:
-        return domlist[0]
-    return None
-    
-
-def append_deferred(dlist, v):
-    if isinstance(v, defer.Deferred):
-        dlist.append(v)
-
-def _vm_configure1(val, vm):
-    d = vm.create_devices()
-    print '_vm_configure1> made devices...'
-    def cbok(x):
-        print '_vm_configure1> cbok', x
-        return x
-    d.addCallback(cbok)
-    d.addCallback(_vm_configure2, vm)
-    print '_vm_configure1<'
-    return d
-
-def _vm_configure2(val, vm):
-    print '>callback _vm_configure2...'
-    d = vm.configure_fields()
-    def cbok(results):
-        print '_vm_configure2> cbok', results
-        return vm
-    def cberr(err):
-        print '_vm_configure2> cberr', err
-        vm.destroy()
-        return err
-    d.addCallback(cbok)
-    d.addErrback(cberr)
-    print '<_vm_configure2'
-    return d
-
-class XendDomainInfo:
-    """Virtual machine object."""
-
-    def __init__(self):
-        self.recreate = 0
-        self.config = None
-        self.id = None
-        self.dom = None
-        self.name = None
-        self.memory = None
-        self.image = None
-        self.ramdisk = None
-        self.cmdline = None
-        self.console = None
-        self.devices = {}
-        self.configs = []
-        self.info = None
-        self.ipaddrs = []
-        self.blkif_backend = 0
-        self.netif_backend = 0
-        #todo: state: running, suspended
-        self.state = 'running'
-        #todo: set to migrate info if migrating
-        self.migrate = None
-
-    def setdom(self, dom):
-        self.dom = int(dom)
-        self.id = str(dom)
-        
-    def update(self, info):
-        """Update with  info from xc.domain_getinfo().
-        """
-        self.info = info
-        self.memory = self.info['mem_kb'] / 1024
-
-    def __str__(self):
-        s = "domain"
-        s += " id=" + self.id
-        s += " name=" + self.name
-        s += " memory=" + str(self.memory)
-        if self.console:
-            s += " console=" + self.console.id
-        if self.image:
-            s += " image=" + self.image
-        s += ""
-        return s
-
-    __repr__ = __str__
-
-    def sxpr(self):
-        sxpr = ['domain',
-                ['id', self.id],
-                ['name', self.name],
-                ['memory', self.memory] ]
-        if self.info:
-            run   = (self.info['running'] and 'r') or '-'
-            block = (self.info['blocked'] and 'b') or '-'
-            stop  = (self.info['paused']  and 'p') or '-'
-            susp  = (self.info['shutdown'] and 's') or '-'
-            crash = (self.info['crashed'] and 'c') or '-'
-            state = run + block + stop + susp + crash
-            sxpr.append(['state', state])
-            if self.info['shutdown']:
-                reasons = ["poweroff", "reboot", "suspend"]
-                reason = reasons[self.info['shutdown_reason']]
-                sxpr.append(['shutdown_reason', reason])
-            sxpr.append(['cpu', self.info['cpu']])
-            sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
-        if self.console:
-            sxpr.append(self.console.sxpr())
-        if self.config:
-            sxpr.append(['config', self.config])
-        return sxpr
-
-    def construct(self, config):
-        # todo - add support for scheduling params?
-        self.config = config
-        try:
-            self.name = sxp.child_value(config, 'name')
-            self.memory = int(sxp.child_value(config, 'memory', '128'))
-            self.configure_backends()
-            image = sxp.child_value(config, 'image')
-            image_name = sxp.name(image)
-            image_handler = get_image_handler(image_name)
-            if image_handler is None:
-                raise VmError('unknown image type: ' + image_name)
-            image_handler(self, image)
-            deferred = self.configure()
-        except StandardError, ex:
-            # Catch errors, cleanup and re-raise.
-            self.destroy()
-            raise
-        def cbok(x):
-            print 'vm_create> cbok', x
-            return x
-        deferred.addCallback(cbok)
-        print 'vm_create<'
-        return deferred
-
-    def config_devices(self, name):
-        """Get a list of the 'device' nodes of a given type from the config.
-
-        name   device type
-        return list of device configs
-        """
-        devices = []
-        for d in sxp.children(self.config, 'device'):
-            dev = sxp.child0(d)
-            if dev is None: continue
-            if name == sxp.name(dev):
-                devices.append(dev)
-        return devices
-
-    def add_device(self, type, dev):
-        """Add a device to a virtual machine.
-
-        dev      device to add
-        """
-        dl = self.devices.get(type, [])
-        dl.append(dev)
-        self.devices[type] = dl
-
-    def get_devices(self, type):
-        val = self.devices.get(type, [])
-        return val
-
-    def get_device_by_id(self, type, id):
-        """Get the device with the given id.
-
-        id       device id
-
-        returns  device or None
-        """
-        dl = self.get_devices(type)
-        for d in dl:
-            if d.getprop('id') == id:
-                return d
-        return None
-
-    def get_device_by_index(self, type, idx):
-        """Get the device with the given index.
-
-        idx       device index
-
-        returns  device or None
-        """
-        dl = self.get_devices(type)
-        if 0 <= idx < len(dl):
-            return dl[idx]
-        else:
-            return None
-
-    def add_config(self, val):
-        """Add configuration data to a virtual machine.
-
-        val      data to add
-        """
-        self.configs.append(val)
-
-    def destroy(self):
-        if self.dom <= 0:
-            return 0
-        return xc.domain_destroy(dom=self.dom)
-
-    def died(self):
-        print 'died>', self.dom
-        self.release_devices()
-
-    def release_devices(self):
-        print 'release_devices>', self.dom
-        self.release_vifs()
-        self.release_vbds()
-        self.devices = {}
-
-    def release_vifs(self):
-        print 'release_vifs>', self.dom
-        if self.dom is None: return
-        ctrl = xend.netif_get(self.dom)
-        if ctrl:
-            ctrl.destroy()
-
-    def release_vbds(self):
-        print 'release_vbds>', self.dom
-        if self.dom is None: return
-        ctrl = xend.blkif_get(self.dom)
-        if ctrl:
-            ctrl.destroy()
-
-    def show(self):
-        """Print virtual machine info.
-        """
-        print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory)
-        print "image:"
-        sxp.show(self.image)
-        print
-        for dl in self.devices:
-            for dev in dl:
-                print "device:"
-                sxp.show(dev)
-                print
-        for val in self.configs:
-            print "config:"
-            sxp.show(val)
-            print
-        print "]"
-
-    def init_domain(self):
-        """Initialize the domain memory.
-        """
-        if self.recreate: return
-        memory = self.memory
-        name = self.name
-        cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
-        print 'init_domain>', memory, name, cpu
-        dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
-        if dom <= 0:
-            raise VmError('Creating domain failed: name=%s memory=%d'
-                          % (name, memory))
-        self.setdom(dom)
-
-    def build_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
-        """Build the domain boot image.
-        """
-        if self.recreate: return
-        if len(cmdline) >= 256:
-            print 'Warning: kernel cmdline too long'
-        dom = self.dom
-        buildfn = getattr(xc, '%s_build' % ostype)
-        print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk
-        flags = 0
-        if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
-        if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
-        err = buildfn(dom            = dom,
-                      image          = kernel,
-                      control_evtchn = self.console.port2,
-                      cmdline        = cmdline,
-                      ramdisk        = ramdisk,
-                      flags          = flags)
-        if err != 0:
-            raise VmError('Building domain failed: type=%s dom=%d err=%d'
-                          % (ostype, dom, err))
-
-    def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
-        """Create a domain. Builds the image but does not configure it.
-
-        ostype  OS type
-        kernel  kernel image
-        ramdisk kernel ramdisk
-        cmdline kernel commandline
-        vifs_n  number of network interfaces
-        """
-        print 'create_domain>', ostype, kernel
-        if not self.recreate:
-            if not os.path.isfile(kernel):
-                raise VmError('Kernel image does not exist: %s' % kernel)
-            if ramdisk and not os.path.isfile(ramdisk):
-                raise VMError('Kernel ramdisk does not exist: %s' % ramdisk)
-        print 'create-domain> init_domain...'
-        self.init_domain()
-        print 'create_domain>', 'dom=', self.dom
-        self.console = xendConsole.console_create(self.dom)
-        self.build_domain(ostype, kernel, ramdisk, cmdline, vifs_n)
-        self.image = kernel
-        self.ramdisk = ramdisk
-        self.cmdline = cmdline
-
-    def create_devices(self):
-        """Create the devices for a vm.
-
-        returns Deferred
-        raises VmError for invalid devices
-        """
-        print '>create_devices'
-        dlist = []
-        devices = sxp.children(self.config, 'device')
-        index = {}
-        for d in devices:
-            dev = sxp.child0(d)
-            if dev is None:
-                raise VmError('invalid device')
-            dev_name = sxp.name(dev)
-            dev_index = index.get(dev_name, 0)
-            dev_handler = get_device_handler(dev_name)
-            if dev_handler is None:
-                raise VmError('unknown device type: ' + dev_name)
-            v = dev_handler(self, dev, dev_index)
-            append_deferred(dlist, v)
-            index[dev_name] = dev_index + 1
-        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
-        print '<create_devices'
-        return deferred
-
-    def configure_backends(self):
-        """Set configuration flags if the vm is a backend for netif of blkif.
-        """
-        for c in sxp.children(self.config, 'backend'):
-            name = sxp.name(c)
-            if name == 'blkif':
-                self.blkif_backend = 1
-            elif name == 'netif':
-                self.netif_backend = 1
-            else:
-                raise VmError('invalid backend type:' + str(name))
-
-    def create_backends(self):
-        """Setup the netif and blkif backends.
-        """
-        if self.blkif_backend:
-            xend.blkif_set_control_domain(self.dom, recreate=self.recreate)
-        if self.netif_backend:
-            xend.netif_set_control_domain(self.dom, recreate=self.recreate)
-            
-    def configure(self):
-        """Configure a vm.
-
-        vm         virtual machine
-        config     configuration
-
-        returns Deferred - calls callback with vm
-        """
-        if self.blkif_backend:
-            d = defer.Deferred()
-            d.callback(1)
-        else:
-            d = xend.blkif_create(self.dom, recreate=self.recreate)
-        d.addCallback(_vm_configure1, self)
-        return d
-
-    def dom_configure(self, dom):
-        """Configure a domain.
-
-        dom    domain id
-        returns deferred
-        """
-        d = dom_get(dom)
-        if not d:
-            raise VMError("Domain not found: %d" % dom)
-        try:
-            self.setdom(dom)
-            self.name = d['name']
-            self.memory = d['memory']/1024
-            deferred = self.configure()
-        except StandardError, ex:
-            self.destroy()
-            raise
-        return deferred
-
-    def configure_fields(self):
-        dlist = []
-        index = {}
-        for field in sxp.children(self.config):
-            field_name = sxp.name(field)
-            field_index = index.get(field_name, 0)
-            field_handler = get_config_handler(field_name)
-            # Ignore unknown fields. Warn?
-            if field_handler:
-                v = field_handler(self, self.config, field, field_index)
-                append_deferred(dlist, v)
-            index[field_name] = field_index + 1
-        d = defer.DeferredList(dlist, fireOnOneErrback=1)
-        return d
-
-
-def vm_image_linux(vm, image):
-    """Create a VM for a linux image.
-
-    name      vm name
-    memory    vm memory
-    image     image config
-
-    returns vm
-    """
-    kernel = sxp.child_value(image, "kernel")
-    cmdline = ""
-    ip = sxp.child_value(image, "ip", "dhcp")
-    if ip:
-        cmdline += " ip=" + ip
-    root = sxp.child_value(image, "root")
-    if root:
-        cmdline += " root=" + root
-    args = sxp.child_value(image, "args")
-    if args:
-        cmdline += " " + args
-    ramdisk = sxp.child_value(image, "ramdisk", '')
-    vifs = vm.config_devices("vif")
-    vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs))
-    return vm
-
-def vm_image_netbsd(vm, image):
-    """Create a VM for a bsd image.
-
-    name      vm name
-    memory    vm memory
-    image     image config
-
-    returns vm
-    """
-    #todo: Same as for linux. Is that right? If so can unify them.
-    kernel = sxp.child_value(image, "kernel")
-    cmdline = ""
-    ip = sxp.child_value(image, "ip", "dhcp")
-    if ip:
-        cmdline += "ip=" + ip
-    root = sxp.child_value(image, "root")
-    if root:
-        cmdline += "root=" + root
-    args = sxp.child_value(image, "args")
-    if args:
-        cmdline += " " + args
-    ramdisk = sxp.child_value(image, "ramdisk")
-    vifs = vm.config_devices("vif")
-    vm.create_domain("netbsd", kernel, ramdisk, cmdline, len(vifs))
-    return vm
-
-
-def vm_dev_vif(vm, val, index):
-    """Create a virtual network interface (vif).
-
-    vm        virtual machine
-    val       vif config
-    index     vif index
-    """
-    if vm.netif_backend:
-        raise VmError('vif: vif in netif backend domain')
-    vif = index #todo
-    vmac = sxp.child_value(val, "mac")
-    defer = make_vif(vm.dom, vif, vmac, vm.recreate)
-    def fn(id):
-        dev = xend.netif_dev(vm.dom, vif)
-        devid = sxp.attribute(val, 'id')
-        if devid:
-            dev.setprop('id', devid)
-        bridge = sxp.child_value(val, "bridge")
-        dev.bridge_add(bridge)
-        vm.add_device('vif', dev)
-        print 'vm_dev_vif> created', dev
-        return id
-    defer.addCallback(fn)
-    return defer
-
-def vm_dev_vbd(vm, val, index):
-    """Create a virtual block device (vbd).
-
-    vm        virtual machine
-    val       vbd config
-    index     vbd index
-    """
-    if vm.blkif_backend:
-        raise VmError('vbd: vbd in blkif backend domain')
-    vdev = index
-    uname = sxp.child_value(val, 'uname')
-    if not uname:
-        raise VMError('vbd: Missing uname')
-    dev = sxp.child_value(val, 'dev')
-    if not dev:
-        raise VMError('vbd: Missing dev')
-    mode = sxp.child_value(val, 'mode', 'r')
-    defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
-    def fn(vbd):
-        dev = xend.blkif_dev(vm.dom, vdev)
-        vm.add_device('vbd', dev)
-        return vbd
-    defer.addCallback(fn)
-    return defer
-
-def parse_pci(val):
-    if isinstance(val, StringType):
-        radix = 10
-        if val.startswith('0x') or val.startswith('0X'):
-            radix = 16
-        v = int(val, radix)
-    else:
-        v = val
-    return v
-
-def vm_dev_pci(vm, val, index):
-    bus = sxp.child_value(val, 'bus')
-    if not bus:
-        raise VMError('pci: Missing bus')
-    dev = sxp.child_value(val, 'dev')
-    if not dev:
-        raise VMError('pci: Missing dev')
-    func = sxp.child_value(val, 'func')
-    if not func:
-        raise VMError('pci: Missing func')
-    try:
-        bus = parse_pci(bus)
-        dev = parse_pci(dev)
-        func = parse_pci(func)
-    except:
-        raise VMError('pci: invalid parameter')
-    rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev,
-                                      func=func, enable=1)
-    if rc < 0:
-        #todo non-fatal
-        raise VMError('pci: Failed to configure device: bus=%s dev=%s func=%s' %
-                      (bus, dev, func))
-    return rc
-    
-
-def vm_field_vfr(vm, config, val, index):
-    """Handle a vfr field in a config.
-
-    vm        virtual machine
-    config    vm config
-    val       vfr field
-    """
-    # Get the rules and add them.
-    # (vfr (vif (id foo) (ip x.x.x.x)) ... ) 
-    list = sxp.children(val, 'vif')
-    ipaddrs = []
-    for v in list:
-        id = sxp.child_value(v, 'id')
-        if id is None:
-            raise VmError('vfr: missing vif id')
-        id = int(id)
-        dev = vm.get_device_by_index('vif', id)
-        if not dev:
-            raise VmError('vfr: invalid vif id %d' % id)
-        vif = sxp.child_value(dev, 'vif')
-        ip = sxp.child_value(v, 'ip')
-        if not ip:
-            raise VmError('vfr: missing ip address')
-        ipaddrs.append(ip);
-        #Don't do this in new i/o model.
-        #print 'vm_field_vfr> add rule', 'dom=', vm.dom, 'vif=', vif, 'ip=', ip
-        #xenctl.ip.setup_vfr_rules_for_vif(vm.dom, vif, ip)
-    vm.ipaddrs = ipaddrs
-
-def vnet_bridge(vnet, vmac, dom, idx):
-    """Add the device for the vif to the bridge for its vnet.
-    """
-    vif = "vif%d.%d" % (dom, idx)
-    try:
-        cmd = "(vif.conn (vif %s) (vnet %s) (vmac %s))" % (vif, vnet, vmac)
-        print "*** vnet_bridge>", cmd
-        out = file("/proc/vnet/policy", "wb")
-        out.write(cmd)
-        err = out.close()
-        print "vnet_bridge>", "err=", err
-    except IOError, ex:
-        print "vnet_bridge>", ex
-    
-def vm_field_vnet(vm, config, val, index):
-    """Handle a vnet field in a config.
-
-    vm        virtual machine
-    config    vm config
-    val       vnet field
-    index     index
-    """
-    # Get the vif children. For each vif look up the vif device
-    # with the given id and configure its vnet.
-    # (vnet (vif (id foo) (vnet 2) (mac x:x:x:x:x:x)) ... )
-    vif_vnets = sxp.children(val, 'vif')
-    for v in vif_vnets:
-        id = sxp.child_value(v, 'id')
-        if id is None:
-            raise VmError('vnet: missing vif id')
-        dev = vm.get_device_by_id('vif', id)
-        #vnet = sxp.child_value(v, 'vnet', 1)
-        #mac = sxp.child_value(dev, 'mac')
-        #vif = sxp.child_value(dev, 'vif')
-        #vnet_bridge(vnet, mac, vm.dom, 0)
-        #vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
-
-# Register image handlers for linux and bsd.
-add_image_handler('linux',  vm_image_linux)
-add_image_handler('netbsd', vm_image_netbsd)
-
-# Register device handlers for vifs and vbds.
-add_device_handler('vif',  vm_dev_vif)
-add_device_handler('vbd',  vm_dev_vbd)
-add_device_handler('pci',  vm_dev_pci)
-
-# Register config handlers for vfr and vnet.
-add_config_handler('vfr',  vm_field_vfr)
-add_config_handler('vnet', vm_field_vnet)
diff --git a/tools/xenmgr/lib/XendMigrate.py b/tools/xenmgr/lib/XendMigrate.py
deleted file mode 100644 (file)
index 1580ba8..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-import sys
-import socket
-
-import sxp
-import XendDB
-import EventServer; eserver = EventServer.instance()
-
-class XendMigrateInfo:
-
-    # states: begin, active, failed, succeeded?
-
-    def __init__(self, id, dom, dst):
-        self.id = id
-        self.state = 'begin'
-        self.src_host = socket.gethostname()
-        self.src_dom = dom
-        self.dst_host = dst
-        self.dst_dom = None
-        
-    def set_state(self, state):
-        self.state = state
-
-    def get_state(self):
-        return self.state
-
-    def sxpr(self):
-        sxpr = ['migrate', ['id', self.id], ['state', self.state] ]
-        sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ]
-        sxpr.append(sxpr_src)
-        sxpr_dst = ['dst', ['host', self.dst] ]
-        if self.dst_dom:
-            sxpr_dst.append(['domain', self.dst_dom])
-        sxpr.append(sxpr_dst)
-        return sxpr
-    
-
-class XendMigrate:
-    # Represents migration in progress.
-    # Use log for indications of begin/end/errors?
-    # Need logging of: domain create/halt, migrate begin/end/fail
-    # Log via event server?
-
-    dbpath = "migrate"
-    
-    def __init__(self):
-        self.db = XendDB.XendDB(self.dbpath)
-        self.migrate = {}
-        self.migrate_db = self.db.fetchall("")
-        self.id = 0
-
-    def nextid(self):
-        self.id += 1
-        return "%d" % self.id
-
-    def sync(self):
-        self.db.saveall("", self.migrate_db)
-
-    def sync_migrate(self, id):
-        self.db.save(id, self.migrate_db[id])
-
-    def close(self):
-        pass
-
-    def _add_migrate(self, id, info):
-        self.migrate[id] = info
-        self.migrate_db[id] = info.sxpr()
-        self.sync_migrate(id)
-        #eserver.inject('xend.migrate.begin', info.sxpr())
-
-    def _delete_migrate(self, id):
-        #eserver.inject('xend.migrate.end', id)
-        del self.migrate[id]
-        del self.migrate_db[id]
-        self.db.delete(id)
-
-    def migrate_ls(self):
-        return self.migrate.keys()
-
-    def migrates(self):
-        return self.migrate.values()
-
-    def migrate_get(self, id):
-        return self.migrate.get(id)
-    
-    def migrate_begin(self, dom, dst):
-        # Check dom for existence, not migrating already.
-        # Create migrate info, tell xend to migrate it?
-        # - or fork migrate command ourselves?
-        # Subscribe to migrate notifications (for updating).
-        id = self.nextid()
-        info = XenMigrateInfo(id, dom, dst)
-        self._add_migrate(id, info)
-        return id
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendMigrate()
-    return inst
diff --git a/tools/xenmgr/lib/XendNode.py b/tools/xenmgr/lib/XendNode.py
deleted file mode 100644 (file)
index d293da8..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Handler for node operations.
- Has some persistent state:
- - logs
- - notification urls
-
-"""
-
-import os
-import Xc
-
-class XendNode:
-
-    def __init__(self):
-        self.xc = Xc.new()
-
-    def shutdown(self):
-        return 0
-
-    def reboot(self):
-        return 0
-
-    def notify(self, uri):
-        return 0
-    
-    def cpu_bvt_slice_set(self, slice):
-        ret = 0
-        #ret = self.xc.bvtsched_global_set(ctx_allow=slice)
-        return ret
-
-    def cpu_bvt_slice_get(self, slice):
-        ret = 0
-        #ret = self.xc.bvtsched_global_get()
-        return ret
-    
-    def cpu_rrobin_slice_set(self, slice):
-        ret = 0
-        #ret = self.xc.rrobin_global_set(slice)
-        return ret
-
-    def info(self):
-        return self.nodeinfo() + self.physinfo()
-
-    def nodeinfo(self):
-        (sys, host, rel, ver, mch) = os.uname()
-        return [['system',  sys],
-                ['host',    host],
-                ['release', rel],
-                ['version', ver],
-                ['machine', mch]]
-
-    def physinfo(self):
-        pinfo = self.xc.physinfo()
-        info = [['cores', pinfo['cores']],
-                ['hyperthreads_per_core', pinfo['ht_per_core']],
-                ['cpu_mhz', pinfo['cpu_khz']/1000],
-                ['memory', pinfo['total_pages']/256],
-                ['free_memory', pinfo['free_pages']/256]]
-        return info
-        
-        
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendNode()
-    return inst
-
diff --git a/tools/xenmgr/lib/XendRoot.py b/tools/xenmgr/lib/XendRoot.py
deleted file mode 100644 (file)
index 665f5df..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Xend root class.
-Creates the event server and handles configuration.
-"""
-
-import os
-import os.path
-import sys
-import EventServer
-
-# Initial create of the event server.
-eserver = EventServer.instance()
-
-import sxp
-
-def reboots():
-    """Get a list of system reboots from wtmp.
-    """
-    out = os.popen('/usr/bin/last reboot', 'r')
-    list = [ x.strip() for x in out if x.startswith('reboot') ]
-    return list
-
-def last_reboot():
-    """Get the last known system reboot.
-    """
-    l = reboots()
-    return (l and l[-1]) or None
-
-class XendRoot:
-    """Root of the management classes."""
-
-    lastboot_default = "/var/xen/lastboot"
-
-    """Default path to the root of the database."""
-    dbroot_default = "/var/xen/xend-db"
-
-    """Default path to the config file."""
-    config_default = "/etc/xen/xend-config.sxp"
-
-    """Environment variable used to override config_default."""
-    config_var     = "XEND_CONFIG"
-
-    def __init__(self):
-        self.rebooted = 0
-        self.last_reboot = None
-        self.dbroot = None
-        self.config_path = None
-        self.config = None
-        self.configure()
-        self.check_lastboot()
-        eserver.subscribe('xend.*', self.event_handler)
-        #eserver.subscribe('xend.domain.created', self.event_handler)
-        #eserver.subscribe('xend.domain.died', self.event_handler)
-
-    def start(self):
-        eserver.inject('xend.start', self.rebooted)
-
-    def event_handler(self, event, val):
-        print >> sys.stderr, "EVENT>", event, val
-
-    def read_lastboot(self):
-        try:
-            val = file(self.lastboot, 'rb').readlines()[0]
-        except StandardError, ex:
-            print 'warning: Error reading', self.lastboot, ex
-            val = None
-        return val
-
-    def write_lastboot(self, val):
-        if not val: return
-        try:
-            fdir = os.path.dirname(self.lastboot)
-            if not os.path.isdir(fdir):
-                os.makedirs(fdir)
-            out = file(self.lastboot, 'wb+')
-            out.write(val)
-            out.close()
-        except IOError, ex:
-            print 'warning: Error writing', self.lastboot, ex
-            pass
-
-    def check_lastboot(self):
-        """Check if there has been a system reboot since we saved lastboot.
-        """
-        last_val = self.read_lastboot()
-        this_val = last_reboot()
-        if this_val == last_val:
-            self.rebooted = 0
-        else:
-            self.rebooted = 1
-            self.write_lastboot(this_val)
-        self.last_reboot = this_val
-
-    def get_last_reboot(self):
-        return self.last_reboot
-
-    def get_rebooted(self):
-        return self.rebooted
-
-    def configure(self):
-        self.set_config()
-        self.dbroot = self.get_config_value("dbroot", self.dbroot_default)
-        self.lastboot = self.get_config_value("lastboot", self.lastboot_default)
-
-    def get_dbroot(self):
-        """Get the path to the database root.
-        """
-        return self.dbroot
-
-    def set_config(self):
-        """If the config file exists, read it. If not, ignore it.
-
-        The config file is a sequence of sxp forms.
-        """
-        self.config_path = os.getenv(self.config_var, self.config_default)
-        if os.path.exists(self.config_path):
-            fin = file(self.config_path, 'rb')
-            try:
-                config = sxp.parse(fin)
-                config.insert(0, 'config')
-                self.config = config
-            finally:
-                fin.close()
-        else:
-            self.config = ['config']
-
-    def get_config(self, name=None):
-        """Get the configuration element with the given name, or
-        the whole configuration if no name is given.
-
-        name   element name (optional)
-        returns config or none
-        """
-        if name is None:
-            val = self.config
-        else:
-            val = sxp.child(self.config, name)
-        return val
-
-    def get_config_value(self, name, val=None):
-        """Get the value of an atomic configuration element.
-
-        name   element name
-        val    default value (optional, defaults to None)
-        returns value
-        """
-        return sxp.child_value(self.config, name, val=val)
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendRoot()
-    return inst
diff --git a/tools/xenmgr/lib/XendVnet.py b/tools/xenmgr/lib/XendVnet.py
deleted file mode 100644 (file)
index 213408e..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Handler for vnet operations.
-"""
-
-import sxp
-import XendDB
-
-class XendVnet:
-    """Index of all vnets. Singleton.
-    """
-
-    dbpath = "vnet"
-
-    def __init__(self):
-        # Table of vnet info indexed by vnet id.
-        self.vnet = {}
-        self.db = XendDB.XendDB(self.dbpath)
-        self.vnet = self.db.fetchall("")
-
-    def vnet_ls(self):
-        """List all vnets.
-        """
-        return self.vnet.keys()
-
-    def vnets(self):
-        return self.vnet.values()
-
-    def vnet_get(self, id):
-        """Get a vnet.
-
-        id     vnet id
-        """
-        return self.vnet.get(id)
-
-    def vnet_create(self, info):
-        """Create a vnet.
-
-        info   config
-        """
-        self.vnet_configure(info)
-
-    def vnet_configure(self, info):
-        """Configure a vnet.
-        id     vnet id
-        info   config
-        """
-        # Need to configure for real.
-        # Only sync if succeeded - otherwise need to back out.
-        self.vnet[info.id] = info
-        self.db.save(info.id, info)
-
-    def vnet_delete(self, id):
-        """Delete a vnet.
-
-        id     vnet id
-        """
-        # Need to delete for real. What if fails?
-        if id in self.vnet:
-            del self.vnet[id]
-            self.db.delete(id)
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendVnet()
-    return inst
diff --git a/tools/xenmgr/lib/__init__.py b/tools/xenmgr/lib/__init__.py
deleted file mode 100644 (file)
index 8d1c8b6..0000000
+++ /dev/null
@@ -1 +0,0 @@
diff --git a/tools/xenmgr/lib/encode.py b/tools/xenmgr/lib/encode.py
deleted file mode 100644 (file)
index 38c9351..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Encoding for arguments to HTTP calls.
-   Uses the url-encoding with MIME type 'application/x-www-form-urlencoded'
-   if the data does not include files. Otherwise it uses the encoding with
-   MIME type 'multipart/form-data'. See the HTML4 spec for details.
-
-   """
-import sys
-import types
-from StringIO import StringIO
-
-import urllib
-import httplib
-import random
-import md5
-
-# Extract from HTML4 spec.
-## The following example illustrates "multipart/form-data"
-## encoding. Suppose we have the following form:
-
-##  <FORM action="http://server.com/cgi/handle"
-##        enctype="multipart/form-data"
-##        method="post">
-##    <P>
-##    What is your name? <INPUT type="text" name="submit-name"><BR>
-##    What files are you sending? <INPUT type="file" name="files"><BR>
-##    <INPUT type="submit" value="Send"> <INPUT type="reset">
-##  </FORM>
-
-## If the user enters "Larry" in the text input, and selects the text
-## file "file1.txt", the user agent might send back the following data:
-
-##    Content-Type: multipart/form-data; boundary=AaB03x
-
-##    --AaB03x
-##    Content-Disposition: form-data; name="submit-name"
-
-##    Larry
-##    --AaB03x
-##    Content-Disposition: form-data; name="files"; filename="file1.txt"
-##    Content-Type: text/plain
-
-##    ... contents of file1.txt ...
-##    --AaB03x--
-
-## If the user selected a second (image) file "file2.gif", the user agent
-## might construct the parts as follows:
-
-##    Content-Type: multipart/form-data; boundary=AaB03x
-
-##    --AaB03x
-##    Content-Disposition: form-data; name="submit-name"
-
-##    Larry
-##    --AaB03x
-##    Content-Disposition: form-data; name="files"
-##    Content-Type: multipart/mixed; boundary=BbC04y
-
-##    --BbC04y
-##    Content-Disposition: file; filename="file1.txt"
-##    Content-Type: text/plain
-
-##    ... contents of file1.txt ...
-##    --BbC04y
-##    Content-Disposition: file; filename="file2.gif"
-##    Content-Type: image/gif
-##    Content-Transfer-Encoding: binary
-
-##    ...contents of file2.gif...
-##    --BbC04y--
-##    --AaB03x--
-
-__all__ = ['encode_data', 'encode_multipart', 'encode_form', 'mime_boundary' ]
-
-def data_values(d):
-    if isinstance(d, types.DictType):
-        return d.items()
-    else:
-        return d
-
-def encode_data(d):
-    """Encode some data for HTTP transport.
-    The encoding used is stored in 'Content-Type' in the headers.
-
-    d  data - sequence of tuples or dictionary
-    returns a 2-tuple of the headers and the encoded data
-    """
-    val = ({}, None)
-    if d is None: return val
-    multipart = 0
-    for (k, v) in data_values(d):
-        if encode_isfile(v):
-            multipart = 1
-            break
-    if multipart:
-        val = encode_multipart(d)
-    else:
-        val = encode_form(d)
-    return val
-
-def encode_isfile(v):
-    if isinstance(v, types.FileType):
-        return 1
-    if hasattr(v, 'readlines'):
-        return 1
-    return 0
-
-def encode_multipart(d):
-    boundary = mime_boundary()
-    hdr = { 'Content-Type': 'multipart/form-data; boundary=' + boundary }
-    out = StringIO()
-    for (k,v) in data_values(d):
-        out.write('--')
-        out.write(boundary)
-        out.write('\r\n')
-        if encode_isfile(v):
-            out.write('Content-Disposition: form-data; name="')
-            out.write(k)
-            if hasattr(v, 'name'):
-                out.write('"; filename="')
-                out.write(v.name)
-            out.write('"\r\n')
-            out.write('Content-Type: application/octet-stream\r\n')
-            out.write('\r\n')
-            for l in v.readlines():
-               out.write(l)  
-        else:
-            out.write('Content-Disposition: form-data; name="')
-            out.write(k)
-            out.write('"\r\n')
-            out.write('\r\n')
-            out.write(str(v))
-            out.write('\r\n')
-    out.write('--')
-    out.write(boundary)
-    out.write('--')
-    out.write('\r\n')
-    return (hdr, out.getvalue())
-
-def mime_boundary():
-    random.seed()
-    m = md5.new()
-    for i in range(0, 10):
-        c = chr(random.randint(1, 255))
-        m.update(c)
-    b = m.hexdigest()
-    return b[0:16]
-
-def encode_form(d):
-    hdr = { 'Content-Type': 'application/x-www-form-urlencoded' }
-    val = urllib.urlencode(d)
-    return (hdr, val)
-
-def main():
-    #d = {'a': 1, 'b': 'x y', 'c': file('conf.sxp') }
-    #d = {'a': 1, 'b': 'x y' }
-    d = [ ('a', 1), ('b', 'x y'), ('c', file('conf.sxp')) ]
-    #d = [ ('a', 1), ('b', 'x y')]
-    v = encode_data(d)
-    print v[0]
-    sys.stdout.write(v[1])
-    print
-
-if __name__ == "__main__":
-    main()
diff --git a/tools/xenmgr/lib/server/SrvBase.py b/tools/xenmgr/lib/server/SrvBase.py
deleted file mode 100644 (file)
index 722b60f..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-import cgi
-
-import os
-import sys
-import types
-import StringIO
-
-from twisted.internet import defer
-from twisted.internet import reactor
-from twisted.web import error
-from twisted.web import resource
-from twisted.web import server
-
-from xenmgr import sxp
-from xenmgr import PrettyPrint
-
-def uri_pathlist(p):
-    """Split a path into a list.
-    p          path
-    return list of path elements
-    """
-    l = []
-    for x in p.split('/'):
-        if x == '': continue
-        l.append(x)
-    return l
-
-class SrvBase(resource.Resource):
-    """Base class for services.
-    """
-
-    def parse_form(self, req, method):
-        """Parse the data for a request, GET using the URL, POST using encoded data.
-        Posts should use enctype='multipart/form-data' in the <form> tag,
-        rather than 'application/x-www-form-urlencoded'. Only 'multipart/form-data'
-        handles file upload.
-
-        req            request
-        returns a cgi.FieldStorage instance
-        """
-        env = {}
-        env['REQUEST_METHOD'] = method
-        if self.query:
-            env['QUERY_STRING'] = self.query
-        val = cgi.FieldStorage(fp=req.rfile, headers=req.headers, environ=env)
-        return val
-    
-    def use_sxp(self, req):
-        """Determine whether to send an SXP response to a request.
-        Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept.
-
-        req            request
-        returns 1 for SXP, 0 otherwise
-        """
-        ok = 0
-        user_agent = req.getHeader('User-Agent')
-        accept = req.getHeader('Accept')
-        if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0):
-            ok = 1
-        return ok
-
-    def get_op_method(self, op):
-        """Get the method for an operation.
-        For operation 'foo' looks for 'op_foo'.
-
-        op     operation name
-        returns method or None
-        """
-        op_method_name = 'op_' + op
-        return getattr(self, op_method_name, None)
-        
-    def perform(self, req):
-        """General operation handler for posted operations.
-        For operation 'foo' looks for a method op_foo and calls
-        it with op_foo(op, req). Replies with code 500 if op_foo
-        is not found.
-
-        The method must return a list when req.use_sxp is true
-        and an HTML string otherwise (or list).
-        Methods may also return a Deferred (for incomplete processing).
-
-        req    request
-        """
-        op = req.args.get('op')
-        if op is None or len(op) != 1:
-            req.setResponseCode(404, "Invalid")
-            return ''
-        op = op[0]
-        op_method = self.get_op_method(op)
-        if op_method is None:
-            req.setResponseCode(501, "Not implemented")
-            req.setHeader("Content-Type", "text/plain")
-            req.write("Not implemented: " + op)
-            return ''
-        else:
-            val = op_method(op, req)
-            if isinstance(val, defer.Deferred):
-                val.addCallback(self._cb_perform, req, 1)
-                return server.NOT_DONE_YET
-            else:
-                self._cb_perform(val, req, 0)
-                return ''
-
-    def _cb_perform(self, val, req, dfr):
-        """Callback to complete the request.
-        May be called from a Deferred.
-        """
-        if isinstance(val, error.ErrorPage):
-            req.write(val.render(req))
-        elif self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(val, req)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            if isinstance(val, types.ListType):
-                req.write('<code><pre>')
-                PrettyPrint.prettyprint(val, out=req)
-                req.write('</pre></code>')
-            else:
-                req.write(str(val))
-            req.write('</body></html>')
-        if dfr:
-            req.finish()
-
-    def print_path(self, req):
-        """Print the path with hyperlinks.
-        """
-        pathlist = [x for x in req.prepath if x != '' ]
-        s = "/"
-        req.write('<h1><a href="/">/</a>')
-        for x in pathlist:
-            s += x + "/"
-            req.write(' <a href="%s">%s</a>/' % (s, x))
-        req.write("</h1>")
diff --git a/tools/xenmgr/lib/server/SrvConsole.py b/tools/xenmgr/lib/server/SrvConsole.py
deleted file mode 100644 (file)
index ea25bb6..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xenmgr import sxp
-from xenmgr import XendConsole
-from SrvDir import SrvDir
-
-class SrvConsole(SrvDir):
-    """An individual console.
-    """
-
-    def __init__(self, info):
-        SrvDir.__init__(self)
-        self.info = info
-        self.xc = XendConsole.instance()
-
-    def op_disconnect(self, op, req):
-        val = self.xc.console_disconnect(self.info.id)
-        return val
-
-    def render_POST(self, req):
-        return self.perform(req)
-        
-    def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(self.info.sxpr(), out=req)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            #self.ls()
-            req.write('<p>%s</p>' % self.info)
-            req.write('<p><a href="%s">Connect to domain %d</a></p>'
-                      % (self.info.uri(), self.info.dom2))
-            self.form(req)
-            req.write('</body></html>')
-        return ''
-
-    def form(self, req):
-        req.write('<form method="post" action="%s">' % req.prePathURL())
-        if self.info.connection():
-            req.write('<input type="submit" name="op" value="disconnect">')
-        req.write('</form>')
diff --git a/tools/xenmgr/lib/server/SrvConsoleDir.py b/tools/xenmgr/lib/server/SrvConsoleDir.py
deleted file mode 100644 (file)
index e5c0308..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from SrvDir import SrvDir
-from SrvConsole import SrvConsole
-from xenmgr import XendConsole
-from xenmgr import sxp
-
-class SrvConsoleDir(SrvDir):
-    """Console directory.
-    """
-
-    def __init__(self):
-        SrvDir.__init__(self)
-        self.xconsole = XendConsole.instance()
-
-    def console(self, x):
-        val = None
-        try:
-            info = self.xconsole.console_get(x)
-            val = SrvConsole(info)
-        except KeyError, ex:
-            print 'SrvConsoleDir>', ex
-            pass
-        return val
-
-    def get(self, x):
-        v = SrvDir.get(self, x)
-        if v is not None:
-            return v
-        v = self.console(x)
-        return v
-
-    def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            self.ls_console(req, 1)
-        else:
-            req.write("<html><head></head><body>")
-            self.print_path(req)
-            self.ls(req)
-            self.ls_console(req)
-            #self.form(req.wfile)
-            req.write("</body></html>")
-        return ''
-
-    def ls_console(self, req, use_sxp=0):
-        url = req.prePathURL()
-        if not url.endswith('/'):
-            url += '/'
-        if use_sxp:
-            consoles = self.xconsole.console_ls()
-            sxp.show(consoles, out=req)
-        else:
-            consoles = self.xconsole.consoles()
-            consoles.sort(lambda x, y: cmp(x.id, y.id))
-            req.write('<ul>')
-            for c in consoles:
-                req.write('<li><a href="%s%s"> %s</a></li>' % (url, c.id, c))
-            req.write('</ul>')
diff --git a/tools/xenmgr/lib/server/SrvConsoleServer.py b/tools/xenmgr/lib/server/SrvConsoleServer.py
deleted file mode 100644 (file)
index d6bb976..0000000
+++ /dev/null
@@ -1,706 +0,0 @@
-###########################################################
-## Xen controller daemon
-## Copyright (c) 2004, K A Fraser (University of Cambridge)
-## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
-###########################################################
-
-import os
-import os.path
-import signal
-import sys
-import socket
-import pwd
-import re
-import StringIO
-
-from twisted.internet import pollreactor
-pollreactor.install()
-
-from twisted.internet import reactor
-from twisted.internet import protocol
-from twisted.internet import abstract
-from twisted.internet import defer
-
-import Xc; xc = Xc.new()
-
-import xend.utils
-
-from xenmgr import sxp
-from xenmgr import PrettyPrint
-from xenmgr import EventServer
-eserver = EventServer.instance()
-
-from xenmgr.server import SrvServer
-
-import channel
-import blkif
-import netif
-import console
-import domain
-from params import *
-
-DEBUG = 1
-
-class MgmtProtocol(protocol.DatagramProtocol):
-    """Handler for the management socket (unix-domain).
-    """
-
-    def __init__(self, daemon):
-        #protocol.DatagramProtocol.__init__(self)
-        self.daemon = daemon
-    
-    def write(self, data, addr):
-        return self.transport.write(data, addr)
-
-    def datagramReceived(self, data, addr):
-        if DEBUG: print 'datagramReceived> addr=', addr, 'data=', data
-        io = StringIO.StringIO(data)
-        try:
-            vals = sxp.parse(io)
-            res = self.dispatch(vals[0])
-            self.send_result(addr, res)
-        except SystemExit:
-            raise
-        except:
-            if DEBUG:
-                raise
-            else:
-                self.send_error(addr)
-
-    def send_reply(self, addr, sxpr):
-        io = StringIO.StringIO()
-        sxp.show(sxpr, out=io)
-        io.seek(0)
-        self.write(io.getvalue(), addr)
-
-    def send_result(self, addr, res):
-        
-        def fn(res, self=self, addr=addr):
-            self.send_reply(addr, ['ok', res])
-            
-        if isinstance(res, defer.Deferred):
-            res.addCallback(fn)
-        else:
-            fn(res)
-
-    def send_error(self, addr):
-        (extype, exval) = sys.exc_info()[:2]
-        self.send_reply(addr, ['err',
-                               ['type',  str(extype) ],
-                               ['value', str(exval)  ] ] )
-
-    def opname(self, name):
-        """Get the name of the method for an operation.
-        """
-        return 'op_' + name.replace('.', '_')
-
-    def operror(self, name, v):
-        """Default operation handler - signals an error.
-        """
-        raise NotImplementedError('Invalid operation: ' +name)
-
-    def dispatch(self, req):
-        """Dispatch a request to its handler.
-        """
-        op_name = sxp.name(req)
-        op_method_name = self.opname(op_name)
-        op_method = getattr(self, op_method_name, self.operror)
-        return op_method(op_name, req)
-
-    def op_console_create(self, name, req):
-        """Create a new control interface - console for a domain.
-        """
-        print name, req
-        dom = sxp.child_value(req, 'domain')
-        if not dom: raise ValueError('Missing domain')
-        dom = int(dom)
-        console_port = sxp.child_value(req, 'console_port')
-        if console_port:
-            console_port = int(console_port)
-        resp = self.daemon.console_create(dom, console_port)
-        print name, resp
-        return resp
-
-    def op_consoles(self, name, req):
-        """Get a list of the consoles.
-        """
-        return self.daemon.consoles()
-
-    def op_console_disconnect(self, name, req):
-        id = sxp.child_value(req, 'id')
-        if not id:
-            raise ValueError('Missing console id')
-        id = int(id)
-        console = self.daemon.get_console(id)
-        if not console:
-            raise ValueError('Invalid console id')
-        if console.conn:
-            console.conn.loseConnection()
-        return ['ok']
-
-    def op_blkifs(self, name, req):
-        pass
-    
-    def op_blkif_devs(self, name, req):
-        pass
-
-    def op_blkif_create(self, name, req):
-        pass
-    
-    def op_blkif_dev_create(self, name, req):
-        pass
-
-    def op_netifs(self, name, req):
-        pass
-
-    def op_netif_devs(self, name, req):
-        pass
-
-    def op_netif_create(self, name, req):
-        pass
-
-    def op_netif_dev_create(self, name, req):
-        pass
-
-class NotifierProtocol(protocol.Protocol):
-    """Asynchronous handler for i/o on the notifier (event channel).
-    """
-
-    def __init__(self, channelFactory):
-        self.channelFactory = channelFactory
-
-    def notificationReceived(self, idx, type):
-        #print 'NotifierProtocol>notificationReceived>', idx, type
-        channel = self.channelFactory.getChannel(idx)
-        if not channel:
-            return
-        #print 'NotifierProtocol>notificationReceived> channel', channel
-        channel.notificationReceived(type)
-
-    def connectionLost(self, reason=None):
-        pass
-
-    def doStart(self):
-        pass
-
-    def doStop(self):
-        pass
-
-    def startProtocol(self):
-        pass
-
-    def stopProtocol(self):
-        pass
-
-class NotifierPort(abstract.FileDescriptor):
-    """Transport class for the event channel.
-    """
-
-    def __init__(self, daemon, notifier, proto, reactor=None):
-        assert isinstance(proto, NotifierProtocol)
-        abstract.FileDescriptor.__init__(self, reactor)
-        self.daemon = daemon
-        self.notifier = notifier
-        self.protocol = proto
-
-    def startListening(self):
-        self._bindNotifier()
-        self._connectToProtocol()
-
-    def stopListening(self):
-        if self.connected:
-            result = self.d = defer.Deferred()
-        else:
-            result = None
-        self.loseConnection()
-        return result
-
-    def fileno(self):
-        return self.notifier.fileno()
-
-    def _bindNotifier(self):
-        self.connected = 1
-
-    def _connectToProtocol(self):
-        self.protocol.makeConnection(self)
-        self.startReading()
-
-    def loseConnection(self):
-        if self.connected:
-            self.stopReading()
-            self.disconnecting = 1
-            reactor.callLater(0, self.connectionLost)
-
-    def connectionLost(self, reason=None):
-        abstract.FileDescriptor.connectionLost(self, reason)
-        if hasattr(self, 'protocol'):
-            self.protocol.doStop()
-        self.connected = 0
-        #self.notifier.close() # Not implemented.
-        os.close(self.fileno())
-        del self.notifier
-        if hasattr(self, 'd'):
-            self.d.callback(None)
-            del self.d
-        
-    def doRead(self):
-        #print 'NotifierPort>doRead>', self
-        count = 0
-        while 1:            
-            #print 'NotifierPort>doRead>', count
-            notification = self.notifier.read()
-            if not notification:
-                break
-            (idx, type) = notification
-            self.protocol.notificationReceived(idx, type)
-            self.notifier.unmask(idx)
-            count += 1
-        #print 'NotifierPort>doRead<'
-
-class EventProtocol(protocol.Protocol):
-    """Asynchronous handler for a connected event socket.
-    """
-
-    def __init__(self, daemon):
-        #protocol.Protocol.__init__(self)
-        self.daemon = daemon
-        # Event queue.
-        self.queue = []
-        # Subscribed events.
-        self.events = []
-        self.parser = sxp.Parser()
-        self.pretty = 0
-
-        # For debugging subscribe to everything and make output pretty.
-        self.subscribe(['*'])
-        self.pretty = 1
-
-    def dataReceived(self, data):
-        try:
-            self.parser.input(data)
-            if self.parser.ready():
-                val = self.parser.get_val()
-                res = self.dispatch(val)
-                self.send_result(res)
-            if self.parser.at_eof():
-                self.loseConnection()
-        except SystemExit:
-            raise
-        except:
-            if DEBUG:
-                raise
-            else:
-                self.send_error()
-
-    def loseConnection(self):
-        if self.transport:
-            self.transport.loseConnection()
-        if self.connected:
-            reactor.callLater(0, self.connectionLost)
-
-    def connectionLost(self, reason=None):
-        self.unsubscribe()
-
-    def send_reply(self, sxpr):
-        io = StringIO.StringIO()
-        if self.pretty:
-            PrettyPrint.prettyprint(sxpr, out=io)
-        else:
-            sxp.show(sxpr, out=io)
-        print >> io
-        io.seek(0)
-        return self.transport.write(io.getvalue())
-
-    def send_result(self, res):
-        return self.send_reply(['ok', res])
-
-    def send_error(self):
-        (extype, exval) = sys.exc_info()[:2]
-        return self.send_reply(['err',
-                                ['type', str(extype)],
-                                ['value', str(exval)]])
-
-    def send_event(self, val):
-        return self.send_reply(['event', val[0], val[1]])
-
-    def unsubscribe(self):
-        for event in self.events:
-            eserver.unsubscribe(event, self.queue_event)
-
-    def subscribe(self, events):
-        self.unsubscribe()
-        for event in events:
-            eserver.subscribe(event, self.queue_event)
-        self.events = events
-
-    def queue_event(self, name, v):
-        # Despite the name we dont' queue the event here.
-        # We send it because the transport will queue it.
-        self.send_event([name, v])
-        
-    def opname(self, name):
-         return 'op_' + name.replace('.', '_')
-
-    def operror(self, name, req):
-        raise NotImplementedError('Invalid operation: ' +name)
-
-    def dispatch(self, req):
-        op_name = sxp.name(req)
-        op_method_name = self.opname(op_name)
-        op_method = getattr(self, op_method_name, self.operror)
-        return op_method(op_name, req)
-
-    def op_help(self, name, req):
-        def nameop(x):
-            if x.startswith('op_'):
-                return x[3:].replace('_', '.')
-            else:
-                return x
-        
-        l = [ nameop(k) for k in dir(self) if k.startswith('op_') ]
-        return l
-
-    def op_quit(self, name, req):
-        self.loseConnection()
-
-    def op_exit(self, name, req):
-        sys.exit(0)
-
-    def op_pretty(self, name, req):
-        self.pretty = 1
-        return ['ok']
-
-    def op_console_disconnect(self, name, req):
-        id = sxp.child_value(req, 'id')
-        if not id:
-            raise ValueError('Missing console id')
-        self.daemon.console_disconnect(id)
-        return ['ok']
-
-    def op_info(self, name, req):
-        val = ['info']
-        val += self.daemon.consoles()
-        val += self.daemon.blkifs()
-        val += self.daemon.netifs()
-        return val
-
-    def op_sys_subscribe(self, name, v):
-        # (sys.subscribe event*)
-        # Subscribe to the events:
-        self.subscribe(v[1:])
-        return ['ok']
-
-    def op_sys_inject(self, name, v):
-        # (sys.inject event)
-        event = v[1]
-        eserver.inject(sxp.name(event), event)
-        return ['ok']
-
-
-class EventFactory(protocol.Factory):
-    """Asynchronous handler for the event server socket.
-    """
-    protocol = EventProtocol
-    service = None
-
-    def __init__(self, daemon):
-        #protocol.Factory.__init__(self)
-        self.daemon = daemon
-
-    def buildProtocol(self, addr):
-        proto = self.protocol(self.daemon)
-        proto.factory = self
-        return proto
-
-class VirqClient:
-    def __init__(self, daemon):
-        self.daemon = daemon
-
-    def virqReceived(self, virq):
-        print 'VirqClient.virqReceived>', virq
-        eserver.inject('xend.virq', virq)
-
-    def lostChannel(self, channel):
-        print 'VirqClient.lostChannel>', channel
-        
-class Daemon:
-    """The xend daemon.
-    """
-    def __init__(self):
-        self.shutdown = 0
-
-    def daemon_pids(self):
-        pids = []
-        pidex = '(?P<pid>\d+)'
-        pythonex = '(?P<python>\S*python\S*)'
-        cmdex = '(?P<cmd>.*)'
-        procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
-        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
-        procs = os.popen('ps -e -o pid,args 2>/dev/null')
-        for proc in procs:
-            pm = procre.match(proc)
-            if not pm: continue
-            xm = xendre.match(pm.group('cmd'))
-            if not xm: continue
-            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
-            pids.append(int(pm.group('pid')))
-        return pids
-
-    def new_cleanup(self, kill=0):
-        err = 0
-        pids = self.daemon_pids()
-        if kill:
-            for pid in pids:
-                print "Killing daemon pid=%d" % pid
-                os.kill(pid, signal.SIGHUP)
-        elif pids:
-            err = 1
-            print "Daemon already running: ", pids
-        return err
-            
-    def cleanup(self, kill=False):
-        # No cleanup to do if PID_FILE is empty.
-        if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
-            return 0
-        # Read the pid of the previous invocation and search active process list.
-        pid = open(PID_FILE, 'r').read()
-        lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
-        for line in lines:
-            if re.search('^ *' + pid + '.+xend', line):
-                if not kill:
-                    print "Daemon is already running (pid %d)" % int(pid)
-                    return 1
-                # Old daemon is still active: terminate it.
-                os.kill(int(pid), 1)
-        # Delete the stale PID_FILE.
-        os.remove(PID_FILE)
-        return 0
-
-    def install_child_reaper(self):
-        #signal.signal(signal.SIGCHLD, self.onSIGCHLD)
-        # Ensure that zombie children are automatically reaped.
-        xend.utils.autoreap()
-
-    def onSIGCHLD(self, signum, frame):
-        code = 1
-        while code > 0:
-            code = os.waitpid(-1, os.WNOHANG)
-
-    def start(self):
-        if self.cleanup(kill=False):
-            return 1
-
-        # Detach from TTY.
-        if not DEBUG:
-            os.setsid()
-
-        if self.set_user():
-            return 1
-
-        self.install_child_reaper()
-
-        # Fork -- parent writes PID_FILE and exits.
-        pid = os.fork()
-        if pid:
-            # Parent
-            pidfile = open(PID_FILE, 'w')
-            pidfile.write(str(pid))
-            pidfile.close()
-            return 0
-        # Child
-        logfile = self.open_logfile()
-        self.redirect_output(logfile)
-        self.run()
-        return 0
-
-    def open_logfile(self):
-        if not os.path.exists(CONTROL_DIR):
-            os.makedirs(CONTROL_DIR)
-
-        # Open log file. Truncate it if non-empty, and request line buffering.
-        if os.path.isfile(LOG_FILE):
-            os.rename(LOG_FILE, LOG_FILE+'.old')
-        logfile = open(LOG_FILE, 'w+', 1)
-        return logfile
-
-    def set_user(self):
-        # Set the UID.
-        try:
-            os.setuid(pwd.getpwnam(USER)[2])
-            return 0
-        except KeyError, error:
-            print "Error: no such user '%s'" % USER
-            return 1
-
-    def redirect_output(self, logfile):
-        if DEBUG: return
-        # Close down standard file handles
-        try:
-            os.close(0) # stdin
-            os.close(1) # stdout
-            os.close(2) # stderr
-        except:
-            pass
-        # Redirect output to log file.
-        sys.stdout = sys.stderr = logfile
-
-    def stop(self):
-        return self.cleanup(kill=True)
-
-    def run(self):
-        self.createFactories()
-        self.listenMgmt()
-        self.listenEvent()
-        self.listenNotifier()
-        self.listenVirq()
-        SrvServer.create(bridge=1)
-        reactor.run()
-
-    def createFactories(self):
-        self.channelF = channel.channelFactory()
-        self.domainCF = domain.DomainControllerFactory()
-        self.blkifCF = blkif.BlkifControllerFactory()
-        self.netifCF = netif.NetifControllerFactory()
-        self.consoleCF = console.ConsoleControllerFactory()
-
-    def listenMgmt(self):
-        protocol = MgmtProtocol(self)
-        s = os.path.join(CONTROL_DIR, MGMT_SOCK)
-        if os.path.exists(s):
-            os.unlink(s)
-        return reactor.listenUNIXDatagram(s, protocol)
-
-    def listenEvent(self):
-        protocol = EventFactory(self)
-        return reactor.listenTCP(EVENT_PORT, protocol)
-
-    def listenNotifier(self):
-        protocol = NotifierProtocol(self.channelF)
-        p = NotifierPort(self, self.channelF.notifier, protocol, reactor)
-        p.startListening()
-        return p
-
-    def listenVirq(self):
-        virqChan = self.channelF.virqChannel(channel.VIRQ_DOM_EXC)
-        virqChan.registerClient(VirqClient(self))
-
-    def exit(self):
-        reactor.diconnectAll()
-        sys.exit(0)
-
-    def blkif_set_control_domain(self, dom, recreate=0):
-        """Set the block device backend control domain.
-        """
-        return self.blkifCF.setControlDomain(dom, recreate=recreate)
-    
-    def blkif_get_control_domain(self, dom):
-        """Get the block device backend control domain.
-        """
-        return self.blkifCF.getControlDomain()
-    
-    def blkif_create(self, dom, recreate=0):
-        """Create a block device interface controller.
-        
-        Returns Deferred
-        """
-        d = self.blkifCF.createInstance(dom, recreate=recreate)
-        return d
-
-    def blkifs(self):
-        return [ x.sxpr() for x in self.blkifCF.getInstances() ]
-
-    def blkif_get(self, dom):
-        return self.blkifCF.getInstanceByDom(dom)
-
-    def blkif_dev(self, dom, vdev):
-        return self.blkifCF.getDomainDevice(dom, vdev)
-
-    def blkif_dev_create(self, dom, vdev, mode, segment, recreate=0):
-        """Create a block device.
-        
-        Returns Deferred
-        """
-        ctrl = self.blkifCF.getInstanceByDom(dom)
-        if not ctrl:
-            raise ValueError('No blkif controller: %d' % dom)
-        print 'blkif_dev_create>', dom, vdev, mode, segment
-        d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate)
-        return d
-
-    def netif_set_control_domain(self, dom, recreate=0):
-        """Set the network interface backend control domain.
-        """
-        return self.netifCF.setControlDomain(dom, recreate=recreate)
-
-    def netif_get_control_domain(self, dom):
-        """Get the network interface backend control domain.
-        """
-        return self.netifCF.getControlDomain()
-    
-    def netif_create(self, dom, recreate=0):
-        """Create a network interface controller.
-        
-        """
-        return self.netifCF.createInstance(dom, recreate=recreate)
-
-    def netifs(self):
-        return [ x.sxpr() for x in self.netifCF.getInstances() ]
-
-    def netif_get(self, dom):
-        return self.netifCF.getInstanceByDom(dom)
-
-    def netif_dev_create(self, dom, vif, vmac, recreate=0):
-        """Create a network device.
-
-        todo
-        """
-        ctrl = self.netifCF.getInstanceByDom(dom)
-        if not ctrl:
-            raise ValueError('No netif controller: %d' % dom)
-        d = ctrl.attachDevice(vif, vmac, recreate=recreate)
-        return d
-
-    def netif_dev(self, dom, vif):
-        return self.netifCF.getDomainDevice(dom, vif)
-
-    def console_create(self, dom, console_port=None):
-        """Create a console for a domain.
-        """
-        console = self.consoleCF.getInstanceByDom(dom)
-        if console is None:
-            console = self.consoleCF.createInstance(dom, console_port)
-        return console.sxpr()
-
-    def consoles(self):
-        return [ c.sxpr() for c in self.consoleCF.getInstances() ]
-
-    def get_console(self, id):
-        return self.consoleCF.getInstance(id)
-
-    def get_domain_console(self, dom):
-        return self.consoleCF.getInstanceByDom(dom)
-
-    def console_disconnect(self, id):
-        """Disconnect any connected console client.
-        """
-        console = self.get_console(id)
-        if not console:
-            raise ValueError('Invalid console id')
-        console.disconnect()
-
-    def domain_shutdown(self, dom, reason):
-        """Shutdown a domain.
-        """
-        ctrl = self.domainCF.getInstanceByDom(dom)
-        if not ctrl:
-            raise ValueError('No domain controller: %d' % dom)
-        ctrl.shutdown(reason)
-        return 0
-        
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = Daemon()
-    return inst
diff --git a/tools/xenmgr/lib/server/SrvDeviceDir.py b/tools/xenmgr/lib/server/SrvDeviceDir.py
deleted file mode 100644 (file)
index 52f4285..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from SrvDir import SrvDir
-
-class SrvDeviceDir(SrvDir):
-    """Device directory.
-    """
-
-    pass
diff --git a/tools/xenmgr/lib/server/SrvDir.py b/tools/xenmgr/lib/server/SrvDir.py
deleted file mode 100644 (file)
index f4310e2..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from twisted.web import error
-from xenmgr import sxp
-from SrvBase import SrvBase
-
-class SrvConstructor:
-    """Delayed constructor for sub-servers.
-    Does not import the sub-server class or create the object until needed.
-    """
-    
-    def __init__(self, klass):
-        """Create a constructor. It is assumed that the class
-        should be imported as 'import klass from klass'.
-
-        klass  name of its class
-        """
-        self.klass = klass
-        self.obj = None
-
-    def getobj(self):
-        """Get the sub-server object, importing its class and instantiating it if
-        necessary.
-        """
-        if not self.obj:
-            exec 'from %s import %s' % (self.klass, self.klass)
-            klassobj = eval(self.klass)
-            self.obj = klassobj()
-        return self.obj
-
-class SrvDir(SrvBase):
-    """Base class for directory servlets.
-    """
-    isLeaf = False
-    
-    def __init__(self):
-        SrvBase.__init__(self)
-        self.table = {}
-        self.order = []
-
-    def getChild(self, x, req):
-        if x == '': return self
-        val = self.get(x)
-        if val is None:
-            return error.NoResource('Not found')
-        else:
-            return val
-
-    def get(self, x):
-        val = self.table.get(x)
-        if val is not None:
-            val = val.getobj()
-        return val
-
-    def add(self, x, xclass = None):
-        if xclass is None:
-            xclass = 'SrvDir'
-        self.table[x] = SrvConstructor(xclass)
-        self.order.append(x)
-
-    def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-type", sxp.mime_type)
-            self.ls(req, 1)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            self.ls(req)
-            self.form(req)
-            req.write('</body></html>')
-        return ''
-            
-    def ls(self, req, use_sxp=0):
-        url = req.prePathURL()
-        if not url.endswith('/'):
-            url += '/'
-        if use_sxp:
-           req.write('(ls ')
-           for k in self.order:
-               req.write(' ' + k)
-           req.write(')')
-        else:
-            req.write('<ul>')
-            for k in self.order:
-                v = self.get(k)
-                req.write('<li><a href="%s%s">%s</a></li>'
-                          % (url, k, k))
-            req.write('</ul>')
-
-    def form(self, req):
-        pass
diff --git a/tools/xenmgr/lib/server/SrvDomain.py b/tools/xenmgr/lib/server/SrvDomain.py
deleted file mode 100644 (file)
index 44d8f4c..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xenmgr import sxp
-from xenmgr import XendDomain
-from xenmgr import XendConsole
-from xenmgr import PrettyPrint
-from xenmgr.Args import FormFn
-
-from SrvDir import SrvDir
-
-class SrvDomain(SrvDir):
-    """Service managing a single domain.
-    """
-
-    def __init__(self, dom):
-        SrvDir.__init__(self)
-        self.dom = dom
-        self.xd = XendDomain.instance()
-        self.xconsole = XendConsole.instance()
-
-    def op_unpause(self, op, req):
-        val = self.xd.domain_unpause(self.dom.id)
-        return val
-        
-    def op_pause(self, op, req):
-        val = self.xd.domain_pause(self.dom.id)
-        return val
-
-    def op_shutdown(self, op, req):
-        val = self.xd.domain_shutdown(self.dom.id)
-        req.setResponseCode(202)
-        req.setHeader("Location", "%s/.." % req.prePathURL())
-        return val
-
-    def op_destroy(self, op, req):
-        val = self.xd.domain_destroy(self.dom.id)
-        req.setHeader("Location", "%s/.." % req.prePathURL())
-        return val
-
-    def op_save(self, op, req):
-        fn = FormFn(self.xd.domain_save,
-                    [['dom', 'int'],
-                     ['file', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_restore(self, op, req):
-        fn = FormFn(self.xd.domain_restore,
-                    [['dom', 'int'],
-                     ['file', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-        
-    def op_migrate(self, op, req):
-        fn = FormFn(self.xd.domain_migrate,
-                    [['dom', 'int'],
-                     ['destination', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        val = 0 # Some migrate id.
-        req.setResponseCode(202)
-        #req.send_header("Location", "%s/.." % self.path) # Some migrate url.
-        return val
-
-    def op_pincpu(self, op, req):
-        fn = FormFn(self.xd.domain_migrate,
-                    [['dom', 'int'],
-                     ['cpu', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_cpu_bvt_set(self, op, req):
-        fn = FormFn(self.xd.domain_cpu_bvt_set,
-                    [['dom', 'int'],
-                     ['mcuadv', 'int'],
-                     ['warp', 'int'],
-                     ['warpl', 'int'],
-                     ['warpu', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_cpu_atropos_set(self, op, req):
-        fn = FormFn(self.xd.domain_cpu_atropos_set,
-                    [['dom', 'int'],
-                     ['period', 'int'],
-                     ['slice', 'int'],
-                     ['latency', 'int'],
-                     ['xtratime', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vifs(self, op, req):
-        return self.xd.domain_vif_ls(self.dom.id)
-
-    def op_vif(self, op, req):
-        fn = FormFn(self.xd.domain_vif_get,
-                    [['dom', 'int'],
-                     ['vif', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vif_stats(self, op, req):
-        #todo
-        fn = FormFn(self.xd.domain_vif_stats,
-                    [['dom', 'int'],
-                     ['vif', 'int']])
-        #val = fn(req.args, {'dom': self.dom.id})
-        val = 999
-        #return val
-        return val
-
-    def op_vif_ip_add(self, op, req):
-        fn = FormFn(self.xd.domain_vif_ip_add,
-                    [['dom', 'int'],
-                     ['vif', 'int'],
-                     ['ip', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vif_scheduler_set(self, op, req):
-        fn = FormFn(self.xd.domain_vif_scheduler_set,
-                    [['dom', 'int'],
-                     ['vif', 'int'],
-                     ['bytes', 'int'],
-                     ['usecs', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vif_scheduler_get(self, op, req):
-        fn = FormFn(self.xd.domain_vif_scheduler_set,
-                    [['dom', 'int'],
-                     ['vif', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vbds(self, op, req):
-        return self.xd.domain_vbd_ls(self.dom.id)
-
-    def op_vbd(self, op, req):
-        fn = FormFn(self.xd.domain_vbd_get,
-                    [['dom', 'int'],
-                     ['vbd', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vbd_add(self, op, req):
-        fn = FormFn(self.xd.domain_vbd_add,
-                    [['dom', 'int'],
-                     ['uname', 'str'],
-                     ['dev', 'str'],
-                     ['mode', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vbd_remove(self, op, req):
-        fn = FormFn(self.xd.domain_vbd_remove,
-                    [['dom', 'int'],
-                     ['dev', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def render_POST(self, req):
-        return self.perform(req)
-        
-    def render_GET(self, req):
-        op = req.args.get('op')
-        if op and op[0] in ['vifs', 'vif', 'vif_stats', 'vbds', 'vbd']:
-            return self.perform(req)
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(self.dom.sxpr(), out=req)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            #self.ls()
-            req.write('<p>%s</p>' % self.dom)
-            if self.dom.console:
-                cinfo = self.dom.console
-                cid = cinfo.id
-                #todo: Local xref: need to know server prefix.
-                req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
-                          % (cid, cid))
-                req.write('<p><a href="%s">Connect to console</a></p>'
-                          % cinfo.uri())
-            if self.dom.config:
-                req.write("<code><pre>")
-                PrettyPrint.prettyprint(self.dom.config, out=req)
-                req.write("</pre></code>")
-            req.write('<a href="%s?op=vif_stats&vif=0">vif 0 stats</a>'
-                      % req.prePathURL())
-            self.form(req)
-            req.write('</body></html>')
-        return ''
-
-    def form(self, req):
-        req.write('<form method="post" action="%s">' % req.prePathURL())
-        req.write('<input type="submit" name="op" value="unpause">')
-        req.write('<input type="submit" name="op" value="pause">')
-        req.write('<input type="submit" name="op" value="shutdown">')
-        req.write('<input type="submit" name="op" value="destroy">')
-        req.write('<br><input type="submit" name="op" value="migrate">')
-        req.write('To: <input type="text" name="destination">')
-        req.write('</form>')
diff --git a/tools/xenmgr/lib/server/SrvDomainDir.py b/tools/xenmgr/lib/server/SrvDomainDir.py
deleted file mode 100644 (file)
index 67a6a9b..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from StringIO import StringIO
-
-from twisted.protocols import http
-from twisted.web import error
-
-from xenmgr import sxp
-from xenmgr import XendDomain
-
-from SrvDir import SrvDir
-from SrvDomain import SrvDomain
-
-class SrvDomainDir(SrvDir):
-    """Service that manages the domain directory.
-    """
-
-    def __init__(self):
-        SrvDir.__init__(self)
-        self.xd = XendDomain.instance()
-
-    def domain(self, x):
-        val = None
-        try:
-            dom = self.xd.domain_get(x)
-            val = SrvDomain(dom)
-        except KeyError, ex:
-            print 'SrvDomainDir>', ex
-            pass
-        return val
-
-    def get(self, x):
-        v = SrvDir.get(self, x)
-        if v is not None:
-            return v
-        v = self.domain(x)
-        return v
-
-    def op_create(self, op, req):
-        ok = 0
-        try:
-            configstring = req.args.get('config')[0]
-            print 'config:', configstring
-            pin = sxp.Parser()
-            pin.input(configstring)
-            pin.input_eof()
-            config = pin.get_val()
-            ok = 1
-        except Exception, ex:
-            print 'op_create>', ex
-        if not ok:
-            req.setResponseCode(http.BAD_REQUEST, "Invalid configuration")
-            return "Invalid configuration"
-            return error.ErrorPage(http.BAD_REQUEST,
-                                   "Invalid",
-                                   "Invalid configuration")
-        try:
-            deferred = self.xd.domain_create(config)
-            deferred.addCallback(self._cb_op_create, configstring, req)
-            return deferred
-        except Exception, ex:
-            raise
-            #return ['err', str(ex) ]
-            #req.setResponseCode(http.BAD_REQUEST, "Error creating domain")
-            #return str(ex)
-            #return error.ErrorPage(http.BAD_REQUEST,
-            #                       "Error creating domain",
-            #                       str(ex))
-                                   
-
-    def _cb_op_create(self, dominfo, configstring, req):
-        """Callback to handle deferred domain creation.
-        """
-        dom = dominfo.id
-        domurl = "%s/%s" % (req.prePathURL(), dom)
-        req.setResponseCode(201, "created")
-        req.setHeader("Location", domurl)
-        if self.use_sxp(req):
-            return dominfo.sxpr()
-        else:
-            out = StringIO()
-            print >> out, ('<p> Created <a href="%s">Domain %s</a></p>'
-                           % (domurl, dom))
-            print >> out, '<p><pre>'
-            print >> out, configstring
-            print >> out, '</pre></p>'
-            val = out.getvalue()
-            out.close()
-            return val
-
-    def render_POST(self, req):
-        return self.perform(req)
-
-    def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            self.ls_domain(req, 1)
-        else:
-            req.write("<html><head></head><body>")
-            self.print_path(req)
-            self.ls(req)
-            self.ls_domain(req)
-            self.form(req)
-            req.write("</body></html>")
-        return ''
-
-    def ls_domain(self, req, use_sxp=0):
-        url = req.prePathURL()
-        if not url.endswith('/'):
-            url += '/'
-        if use_sxp:
-            domains = self.xd.domain_ls()
-            sxp.show(domains, out=req)
-        else:
-            domains = self.xd.domains()
-            domains.sort(lambda x, y: cmp(x.id, y.id))
-            req.write('<ul>')
-            for d in domains:
-               req.write('<li><a href="%s%s"> Domain %s</a>'
-                         % (url, d.id, d.id))
-               req.write('name=%s' % d.name)
-               req.write('memory=%d'% d.memory)
-               req.write('</li>')
-            req.write('</ul>')
-
-    def form(self, req):
-        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
-                  % req.prePathURL())
-        req.write('<button type="submit" name="op" value="create">Create Domain</button>')
-        req.write('Config <input type="file" name="config"><br>')
-        req.write('</form>')
diff --git a/tools/xenmgr/lib/server/SrvEventDir.py b/tools/xenmgr/lib/server/SrvEventDir.py
deleted file mode 100644 (file)
index eda5697..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xenmgr import sxp
-from xenmgr import EventServer
-from SrvDir import SrvDir
-
-class SrvEventDir(SrvDir):
-    """Event directory.
-    """
-
-    def __init__(self):
-        SrvDir.__init__(self)
-        self.eserver = EventServer.instance()
-
-    def op_inject(self, op, req):
-        eventstring = req.args.get('event')
-        pin = sxp.Parser()
-        pin.input(eventstring)
-        pin.input_eof()
-        sxpr = pin.get_val()
-        self.eserver.inject(sxp.name(sxpr), sxpr)
-        if req.use_sxp:
-            sxp.name(sxpr)
-        else:
-            return '<code>' + eventstring + '</code>'
-        
-    def render_POST(self, req):
-        return self.perform(req)
-
-    def form(self, req):
-        action = req.prePathURL()
-        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
-                  % action)
-        req.write('<button type="submit" name="op" value="inject">Inject</button>')
-        req.write('Event <input type="text" name="event" size="40"><br>')
-        req.write('</form>')
-        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
-                  % action)
-        req.write('<button type="submit" name="op" value="inject">Inject</button>')
-        req.write('Event file<input type="file" name="event"><br>')
-        req.write('</form>')
diff --git a/tools/xenmgr/lib/server/SrvNode.py b/tools/xenmgr/lib/server/SrvNode.py
deleted file mode 100644 (file)
index d4411d5..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-import os
-from SrvDir import SrvDir
-from xenmgr import sxp
-from xenmgr import XendNode
-
-class SrvNode(SrvDir):
-    """Information about the node.
-    """
-
-    def __init__(self):
-        SrvDir.__init__(self)
-        self.xn = XendNode.instance()
-
-    def op_shutdown(self, op, req):
-        val = self.xn.shutdown()
-        return val
-
-    def op_reboot(self, op, req):
-        val = self.xn.reboot()
-        return val
-
-    def op_cpu_rrobin_slice_set(self, op, req):
-        fn = FormFn(self.xn.cpu_rrobin_slice_set,
-                    [['slice', 'int']])
-        val = fn(req.args, {})
-        return val
-
-    def op_cpu_bvt_slice_set(self, op, req):
-        fn = FormFn(self.xn.cpu_bvt_slice_set,
-                    [['slice', 'int']])
-        val = fn(req.args, {})
-        return val
-
-    def render_POST(self, req):
-        return self.perform(req)
-
-    def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(['node'] + self.info(), out=req)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            req.write('<ul>')
-            for d in self.info():
-                req.write('<li> %10s: %s' % (d[0], str(d[1])))
-            req.write('</ul>')
-            req.write('</body></html>')
-        return ''
-            
-    def info(self):
-        return self.xn.info()
diff --git a/tools/xenmgr/lib/server/SrvRoot.py b/tools/xenmgr/lib/server/SrvRoot.py
deleted file mode 100644 (file)
index 6256d83..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xenmgr import XendRoot
-xroot = XendRoot.instance()
-from SrvDir import SrvDir
-
-class SrvRoot(SrvDir):
-    """The root of the xend server.
-    """
-
-    """Server sub-components. Each entry is (name, class), where
-    'name' is the entry name and  'class' is the name of its class.
-    """
-    #todo Get this list from the XendRoot config.
-    subdirs = [
-        ('node',    'SrvNode'       ),
-        ('domain',  'SrvDomainDir'  ),
-        ('console', 'SrvConsoleDir' ),
-        ('event',   'SrvEventDir'   ),
-        ('device',  'SrvDeviceDir'  ),
-        ('vnet',    'SrvVnetDir'    ),
-        ]
-
-    def __init__(self):
-        SrvDir.__init__(self)
-        for (name, klass) in self.subdirs:
-            self.add(name, klass)
-        for (name, klass) in self.subdirs:
-            self.get(name)
-        xroot.start()
diff --git a/tools/xenmgr/lib/server/SrvServer.py b/tools/xenmgr/lib/server/SrvServer.py
deleted file mode 100644 (file)
index d507c20..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/python2
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Example xend HTTP and console server.
-
-   Can be accessed from a browser or from a program.
-   Do 'python SrvServer.py' to run the server.
-   Then point a web browser at http://localhost:8000/xend and follow the links.
-   Most are stubs, except /domain which has a list of domains and a 'create domain'
-   button.
-
-   You can also access the server from a program.
-   Do 'python XendClient.py' to run a few test operations.
-
-   The data served differs depending on the client (as defined by User-Agent
-   and Accept in the HTTP headers). If the client is a browser, data
-   is returned in HTML, with interactive forms. If the client is a program,
-   data is returned in SXP format, with no forms.
-
-   The server serves to the world by default. To restrict it to the local host
-   change 'interface' in main().
-
-   Mike Wray <mike.wray@hp.com>
-"""
-# todo Support security settings etc. in the config file.
-# todo Support command-line args.
-
-from twisted.web import server
-from twisted.web import resource
-from twisted.internet import reactor
-
-from xenmgr import XendRoot
-xroot = XendRoot.instance()
-
-from xenmgr import XendBridge
-
-from SrvRoot import SrvRoot
-
-def create(port=None, interface=None, bridge=0):
-    if port is None: port = 8000
-    if interface is None: interface = ''
-    if bridge or xroot.rebooted:
-        init_bridge()
-    root = resource.Resource()
-    xend = SrvRoot()
-    root.putChild('xend', xend)
-    site = server.Site(root)
-    reactor.listenTCP(port, site, interface=interface)
-
-def init_bridge():
-    XendBridge.bridge_create()
-    XendBridge.reconfigure()
-
-def main(port=None, interface=None):
-    create(port, interface)
-    reactor.run()
-
-
-if __name__ == '__main__':
-    main()
diff --git a/tools/xenmgr/lib/server/SrvVnetDir.py b/tools/xenmgr/lib/server/SrvVnetDir.py
deleted file mode 100644 (file)
index a8a8141..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from SrvDir import SrvDir
-
-class SrvVnetDir(SrvDir):
-    """Vnet directory.
-    """
-
-    pass
diff --git a/tools/xenmgr/lib/server/__init__.py b/tools/xenmgr/lib/server/__init__.py
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/xenmgr/lib/server/blkif.py b/tools/xenmgr/lib/server/blkif.py
deleted file mode 100755 (executable)
index fa46e3b..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-from twisted.internet import defer
-
-from xenmgr import sxp
-from xenmgr import PrettyPrint
-
-import channel
-import controller
-from messages import *
-
-class BlkifControllerFactory(controller.ControllerFactory):
-    """Factory for creating block device interface controllers.
-    Also handles the 'back-end' channel to the device driver domain.
-    """
-
-    def __init__(self):
-        controller.ControllerFactory.__init__(self)
-
-        self.majorTypes = [ CMSG_BLKIF_BE ]
-
-        self.subTypes = {
-            CMSG_BLKIF_BE_CREATE     : self.recv_be_create,
-            CMSG_BLKIF_BE_CONNECT    : self.recv_be_connect,
-            CMSG_BLKIF_BE_VBD_CREATE : self.recv_be_vbd_create,
-            CMSG_BLKIF_BE_VBD_GROW   : self.recv_be_vbd_grow,
-            CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
-            }
-        self.attached = 1
-        self.registerChannel()
-
-    def createInstance(self, dom, recreate=0):
-        d = self.addDeferred()
-        blkif = self.getInstanceByDom(dom)
-        if blkif:
-            self.callDeferred(blkif)
-        else:
-            blkif = BlkifController(self, dom)
-            self.addInstance(blkif)
-            if recreate:
-                self.callDeferred(blkif)
-            else:
-                blkif.send_be_create()
-        return d
-
-    def getDomainDevices(self, dom):
-        blkif = self.getInstanceByDom(dom)
-        return (blkif and blkif.getDevices()) or []
-
-    def getDomainDevice(self, dom, vdev):
-        blkif = self.getInstanceByDom(dom)
-        return (blkif and blkif.getDevice(vdev)) or None
-
-    def setControlDomain(self, dom, recreate=0):
-        if self.dom == dom: return
-        self.deregisterChannel()
-        if not recreate:
-            self.attached = 0
-        self.dom = dom
-        self.registerChannel()
-        #
-        #if xend.blkif.be_port:
-        #    xend.blkif.recovery = True
-        #xend.blkif.be_port = xend.main.port_from_dom(dom)
-
-    def getControlDomain(self):
-        return self.dom
-
-    def reattachDevice(self, dom, vdev):
-        blkif = self.getInstanceByDom(dom)
-        if blkif:
-            blkif.reattachDevice(vdev)
-        self.attached = self.devicesAttached()
-        if self.attached:
-            self.reattached()
-
-    def devicesAttached(self):
-        """Check if all devices are attached.
-        """
-        attached = 1
-        for blkif in self.getInstances():
-            if not blkif.attached:
-                attached = 0
-                break
-        return attached
-                         
-    def reattached(self):
-        for blkif in self.getInstances():
-            blkif.reattached()
-
-    def recv_be_create(self, msg, req):
-        #print 'recv_be_create>'
-        val = unpackMsg('blkif_be_create_t', msg)
-        blkif = self.getInstanceByDom(val['domid'])
-        self.callDeferred(blkif)
-    
-    def recv_be_connect(self, msg, req):
-        #print 'recv_be_create>'
-        val = unpackMsg('blkif_be_connect_t', msg)
-        blkif = self.getInstanceByDom(val['domid'])
-        if blkif:
-            blkif.send_fe_interface_status_changed()
-        else:
-            pass
-    
-    def recv_be_vbd_create(self, msg, req):
-        #print 'recv_be_vbd_create>'
-        val = unpackMsg('blkif_be_vbd_create_t', msg)
-        blkif = self.getInstanceByDom(val['domid'])
-        if blkif:
-            blkif.send_be_vbd_grow(val['vdevice'])
-        else:
-            pass
-    
-    def recv_be_vbd_grow(self, msg, req):
-        #print 'recv_be_vbd_grow>'
-        val = unpackMsg('blkif_be_vbd_grow_t', msg)
-        # Check status?
-        if self.attached:
-            self.callDeferred(0)
-        else:
-            self.reattachDevice(val['domid'], val['vdevice'])
-
-    def recv_be_driver_status_changed(self, msg, req):
-        val = unpackMsg('blkif_be_driver_status_changed_t', msg)
-        status = val['status']
-        if status == BLKIF_DRIVER_STATUS_UP and not self.attached:
-            for blkif in self.getInstances():
-                blkif.detach()
-
-class BlkDev(controller.Dev):
-    """Info record for a block device.
-    """
-
-    def __init__(self, ctrl, vdev, mode, segment):
-        controller.Dev.__init__(self, ctrl)
-        self.vdev = vdev
-        self.mode = mode
-        self.device = segment['device']
-        self.start_sector = segment['start_sector']
-        self.nr_sectors = segment['nr_sectors']
-        self.attached = 1
-
-    def readonly(self):
-        return 'w' not in self.mode
-
-    def sxpr(self):
-        val = ['blkdev', ['vdev', self.vdev], ['mode', self.mode] ]
-        return val
-
-    def destroy(self):
-        print 'BlkDev>destroy>', self.vdev
-        PrettyPrint.prettyprint(self.sxpr())
-        self.controller.send_be_vbd_destroy(self.vdev)
-        
-class BlkifController(controller.Controller):
-    """Block device interface controller. Handles all block devices
-    for a domain.
-    """
-    
-    def __init__(self, factory, dom):
-        #print 'BlkifController> dom=', dom
-        controller.Controller.__init__(self, factory, dom)
-        self.devices = {}
-
-        self.majorTypes = [ CMSG_BLKIF_FE ]
-
-        self.subTypes = {
-            CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
-                self.recv_fe_driver_status_changed,
-            CMSG_BLKIF_FE_INTERFACE_CONNECT    :
-                self.recv_fe_interface_connect,
-            }
-        self.attached = 1
-        self.evtchn = None
-        self.registerChannel()
-        #print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx
-
-    def sxpr(self):
-        val = ['blkif', ['dom', self.dom]]
-        if self.evtchn:
-            val.append(['evtchn',
-                        self.evtchn['port1'],
-                        self.evtchn['port2']])
-        return val
-
-    def lostChannel(self):
-        print 'BlkifController>lostChannel>', 'dom=', self.dom
-        #self.destroyDevices()
-        controller.Controller.lostChannel(self)
-
-    def getDevices(self):
-        return self.devices.values()
-
-    def getDevice(self, vdev):
-        return self.devices.get(vdev)
-
-    def addDevice(self, vdev, mode, segment):
-        if vdev in self.devices: return None
-        dev = BlkDev(self, vdev, mode, segment)
-        self.devices[vdev] = dev
-        return dev
-
-    def attachDevice(self, vdev, mode, segment, recreate=0):
-        """Attach a device to the specified interface.
-        """
-        #print 'BlkifController>attach_device>', self.dom, vdev, mode, segment
-        dev = self.addDevice(vdev, mode, segment)
-        if not dev: return -1
-        if recreate:
-            d = defer.Deferred()
-            d.callback(self)
-        else:
-            self.send_be_vbd_create(vdev)
-            d = self.factory.addDeferred()
-        return d
-
-    def destroy(self):
-        print 'BlkifController>destroy> dom=', self.dom
-        def cb_destroy(val):
-            self.send_be_destroy()
-        d = self.factory.addDeferred()
-        d.addCallback(cb_destroy)
-        self.send_be_disconnect()
-        #self.destroyDevices()
-
-    def destroyDevices(self):
-        for dev in self.getDevices():
-            dev.destroy()
-
-    def detach(self):
-        """Detach all devices, when the back-end control domain has changed.
-        """
-        self.attached = 0
-        for dev in self.devices.values():
-            dev.attached = 0
-            self.send_be_vbd_create(vdev)
-
-    def reattachDevice(self, vdev):
-        """Reattach a device, when the back-end control domain has changed.
-        """
-        dev = self.devices[vdev]
-        dev.attached = 1
-        attached = 1
-        for dev in self.devices.values():
-            if not dev.attached:
-                attached = 0
-                break
-        self.attached = attached
-        return self.attached
-
-    def reattached(self):
-        """All devices have been reattached after the back-end control
-        domain has changed.
-        """
-        msg = packMsg('blkif_fe_interface_status_changed_t',
-                      { 'handle' : 0,
-                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED})
-        self.writeRequest(msg)
-
-    def recv_fe_driver_status_changed(self, msg, req):
-        msg = packMsg('blkif_fe_interface_status_changed_t',
-                      { 'handle' : 0,
-                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
-                        'evtchn' : 0 })
-        self.writeRequest(msg)
-    
-    def recv_fe_interface_connect(self, msg, req):
-        val = unpackMsg('blkif_fe_interface_connect_t', msg)
-        self.evtchn = channel.eventChannel(0, self.dom)
-        print 'recv_fe_interface_connect>'
-        PrettyPrint.prettyprint(self.sxpr())
-        msg = packMsg('blkif_be_connect_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : val['handle'],
-                        'evtchn'       : self.evtchn['port1'],
-                        'shmem_frame'  : val['shmem_frame'] })
-        self.factory.writeRequest(msg)
-        pass
-
-    #def recv_fe_interface_status_changed(self, msg, req):
-    #    (hnd, status, chan) = unpackMsg('blkif_fe_interface_status_changed_t', msg)
-    #    print 'recv_fe_interface_status_changed>', hnd, status, chan
-    #   pass
-
-    def send_fe_interface_status_changed(self):
-        msg = packMsg('blkif_fe_interface_status_changed_t',
-                      { 'handle' : 0,
-                        'status' : BLKIF_INTERFACE_STATUS_CONNECTED,
-                        'evtchn' : self.evtchn['port2'] })
-        self.writeRequest(msg)
-
-    def send_be_create(self):
-        msg = packMsg('blkif_be_create_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : 0 })
-        self.factory.writeRequest(msg)
-
-    def send_be_disconnect(self):
-        print '>BlkifController>send_be_disconnect>', 'dom=', self.dom
-        msg = packMsg('blkif_be_disconnect_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : 0 })
-        self.factory.writeRequest(msg)
-
-    def send_be_destroy(self):
-        print '>BlkifController>send_be_destroy>', 'dom=', self.dom
-        msg = packMsg('blkif_be_destroy_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : 0 })
-        self.factory.writeRequest(msg)
-
-    def send_be_vbd_create(self, vdev):
-        dev = self.devices[vdev]
-        msg = packMsg('blkif_be_vbd_create_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : 0,
-                        'vdevice'      : dev.vdev,
-                        'readonly'     : dev.readonly() })
-        self.factory.writeRequest(msg)
-        
-    def send_be_vbd_grow(self, vdev):
-        dev = self.devices[vdev]
-        msg = packMsg('blkif_be_vbd_grow_t',
-                      { 'domid'                : self.dom,
-                        'blkif_handle'         : 0,
-                        'vdevice'              : dev.vdev,
-                        'extent.device'        : dev.device,
-                        'extent.sector_start'  : dev.start_sector,
-                        'extent.sector_length' : dev.nr_sectors })
-        self.factory.writeRequest(msg)
-
-    def send_be_vbd_destroy(self, vdev):
-        print '>BlkifController>send_be_vbd_destroy>', 'dom=', self.dom, 'vdev=', vdev
-        PrettyPrint.prettyprint(self.sxpr())
-        dev = self.devices[vdev]
-        msg = packMsg('blkif_be_vbd_destroy_t',
-                      { 'domid'                : self.dom,
-                        'blkif_handle'         : 0,
-                        'vdevice'              : dev.vdev })
-        del self.devices[vdev]
-        self.factory.writeRequest(msg)
-    
diff --git a/tools/xenmgr/lib/server/channel.py b/tools/xenmgr/lib/server/channel.py
deleted file mode 100755 (executable)
index cf89091..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-import Xc; xc = Xc.new()
-import xend.utils
-from messages import msgTypeName
-
-VIRQ_MISDIRECT  = 0  # Catch-all interrupt for unbound VIRQs.
-VIRQ_TIMER      = 1  # Timebase update, and/or requested timeout.
-VIRQ_DEBUG      = 2  # Request guest to dump debug info.
-VIRQ_CONSOLE    = 3  # (DOM0) bytes received on emergency console.
-VIRQ_DOM_EXC    = 4  # (DOM0) Exceptional event for some domain.
-
-def eventChannel(dom1, dom2):
-    return xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2)
-
-class ChannelFactory:
-    """Factory for creating channels.
-    Maintains a table of channels.
-    """
-
-    """ Channels indexed by index. """
-    channels = {}
-
-    def __init__(self):
-        """Constructor - do not use. Use the channelFactory function."""
-        self.notifier = xend.utils.notifier()
-    
-    def addChannel(self, channel):
-        """Add a channel.
-        """
-        idx = channel.idx
-        self.channels[idx] = channel
-        self.notifier.bind(idx)
-        # Try to wake it up
-        #self.notifier.unmask(idx)
-        #channel.notify()
-
-    def getChannel(self, idx):
-        """Get the channel with the given index (if any).
-        """
-        return self.channels.get(idx)
-
-    def delChannel(self, idx):
-        """Remove the channel with the given index (if any).
-        """
-        if idx in self.channels:
-            del self.channels[idx]
-            self.notifier.unbind(idx)
-
-    def domChannel(self, dom):
-        """Get the channel for the given domain.
-        Construct if necessary.
-        """
-        dom = int(dom)
-        for chan in self.channels.values():
-            if not isinstance(chan, Channel): continue
-            if chan.dom == dom:
-                return chan
-        chan = Channel(self, dom)
-        self.addChannel(chan)
-        return chan
-
-    def virqChannel(self, virq):
-        """Get the channel for the given virq.
-        Construct if necessary.
-        """
-        for chan in self.channels.values():
-            if not isinstance(chan, VirqChannel): continue
-            if chan.virq == virq:
-                return chan
-        chan = VirqChannel(self, virq)
-        self.addChannel(chan)
-        return chan
-
-    def channelClosed(self, channel):
-        """The given channel has been closed - remove it.
-        """
-        self.delChannel(channel.idx)
-
-    def createPort(self, dom):
-        """Create a port for a channel to the given domain.
-        """
-        return xend.utils.port(dom)
-
-def channelFactory():
-    """Singleton constructor for the channel factory.
-    Use this instead of the class constructor.
-    """
-    global inst
-    try:
-        inst
-    except:
-        inst = ChannelFactory()
-    return inst
-
-class BaseChannel:
-    """Abstract superclass for channels.
-
-    The subclass constructor must set idx to the port to use.
-    """
-
-    def __init__(self, factory):
-        self.factory = factory
-        self.idx = -1
-        self.closed = 0
-
-    def getIndex(self):
-        """Get the channel index.
-        """
-        return self.idx
-
-    def notificationReceived(self, type):
-        """Called when a notification is received.
-        Closes the channel on error, otherwise calls
-        handleNotification(type), which should be defined
-        in a subclass.
-        """
-        #print 'notificationReceived> type=', type, self
-        if self.closed: return
-        if type == self.factory.notifier.EXCEPTION:
-            print 'notificationReceived> EXCEPTION'
-            info = xc.evtchn_status(self.idx)
-            if info['status'] == 'unbound':
-                print 'notificationReceived> EXCEPTION closing...'
-                self.close()
-                return
-        self.handleNotification(type)
-
-    def close(self):
-        """Close the channel. Calls channelClosed() on the factory.
-        Override in subclass.
-        """
-        self.factory.channelClosed(self)
-
-    def handleNotification(self, type):
-        """Handle notification.
-        Define in subclass.
-        """
-        pass
-        
-
-class VirqChannel(BaseChannel):
-    """A channel for handling a virq.
-    """
-    
-    def __init__(self, factory, virq):
-        """Create a channel for the given virq using the given factory.
-
-        Do not call directly, use virqChannel on the factory.
-        """
-        BaseChannel.__init__(self, factory)
-        self.virq = virq
-        # Notification port (int).
-        self.port = xc.evtchn_bind_virq(virq)
-        self.idx = self.port
-        # Clients to call when a virq arrives.
-        self.clients = []
-
-    def __repr__(self):
-        return ('<VirqChannel virq=%d port=%d>'
-                % (self.virq, self.port))
-
-    def getVirq(self):
-        """Get the channel's virq.
-        """
-        return self.virq
-
-    def close(self):
-        """Close the channel. Calls lostChannel(self) on all its clients and
-        channelClosed() on the factory.
-        """
-        for c in self.clients:
-            c.lostChannel(self)
-        del self.clients
-        BaseChannel.close(self)
-
-    def registerClient(self, client):
-        """Register a client. The client will be called with
-        client.virqReceived(virq) when a virq is received.
-        The client will be called with client.lostChannel(self) if the
-        channel is closed.
-        """
-        self.clients.append(client)
-
-    def handleNotification(self, type):
-        for c in self.clients:
-            c.virqReceived(self.virq)
-
-    def notify(self):
-        xc.evtchn_send(self.port)
-
-
-class Channel(BaseChannel):
-    """A control channel to a domain. Messages for the domain device controllers
-    are multiplexed over the channel (console, block devs, net devs).
-    """
-
-    def __init__(self, factory, dom):
-        """Create a channel to the given domain using the given factory.
-
-        Do not call directly, use domChannel on the factory.
-        """
-        BaseChannel.__init__(self, factory)
-        # Domain.
-        self.dom = int(dom)
-        # Domain port (object).
-        self.port = self.factory.createPort(dom)
-        # Channel port (int).
-        self.idx = self.port.local_port
-        # Registered devices.
-        self.devs = []
-        # Devices indexed by the message types they handle.
-        self.devs_by_type = {}
-        # Output queue.
-        self.queue = []
-        self.closed = 0
-
-    def getLocalPort(self):
-        """Get the local port.
-        """
-        return self.port.local_port
-
-    def getRemotePort(self):
-        """Get the remote port.
-        """
-        return self.port.remote_port
-
-    def close(self):
-        """Close the channel. Calls lostChannel() on all its devices and
-        channelClosed() on the factory.
-        """
-        self.closed = 1
-        for d in self.devs:
-            d.lostChannel()
-        self.factory.channelClosed(self)
-        self.devs = []
-        self.devs_by_type = {}
-
-    def registerDevice(self, types, dev):
-        """Register a device controller.
-
-        @param types message types the controller handles
-        @param dev   device controller
-        """
-        if self.closed: return
-        self.devs.append(dev)
-        for ty in types:
-            self.devs_by_type[ty] = dev
-
-    def deregisterDevice(self, dev):
-        """Remove the registration for a device controller.
-
-        @param dev device controller
-        """
-        if dev in self.devs:
-            self.devs.remove(dev)
-        types = [ ty for (ty, d) in self.devs_by_type.items() if d == dev ]
-        for ty in types:
-            del self.devs_by_type[ty]
-
-    def getDevice(self, type):
-        """Get the device controller handling a message type.
-
-        @param type message type
-        @returns controller or None
-        """
-        return self.devs_by_type.get(type)
-
-    def getMessageType(self, msg):
-        """Get a 2-tuple of the message type and subtype.
-        """
-        hdr = msg.get_header()
-        return (hdr['type'], hdr.get('subtype'))
-
-    def __repr__(self):
-        return ('<Channel dom=%d ports=%d:%d>'
-                % (self.dom,
-                   self.port.local_port,
-                   self.port.remote_port))
-
-    def handleNotification(self, type):
-        work = 0
-        work += self.handleRequests()
-        work += self.handleResponses()
-        work += self.handleWrites()
-        if work:
-            self.notify()
-
-    def notify(self):
-        self.port.notify()
-
-    def handleRequests(self):
-        work = 0
-        while 1:
-            msg = self.readRequest()
-            if not msg: break
-            self.requestReceived(msg)
-            work += 1
-        return work
-
-    def requestReceived(self, msg):
-        (ty, subty) = self.getMessageType(msg)
-        #todo:  Must respond before writing any more messages.
-        #todo:  Should automate this (respond on write)
-        self.port.write_response(msg)
-        dev = self.getDevice(ty)
-        if dev:
-            dev.requestReceived(msg, ty, subty)
-        else:
-            print ("requestReceived> No device: Message type %s %d:%d"
-                   % (msgTypeName(ty, subty), ty, subty)), self
-
-    def handleResponses(self):
-        work = 0
-        while 1:
-            msg = self.readResponse()
-            if not msg: break
-            self.responseReceived(msg)
-            work += 1
-        return work
-
-    def responseReceived(self, msg):
-        (ty, subty) = self.getMessageType(msg)
-        dev = self.getDevice(ty)
-        if dev:
-            dev.responseReceived(msg, ty, subty)
-        else:
-            print ("responseReceived> No device: Message type %d:%d"
-                   % (msgTypeName(ty, subty), ty, subty)), self
-
-    def handleWrites(self):
-        work = 0
-        # Pull data from producers.
-        for dev in self.devs:
-            work += dev.produceRequests()
-        # Flush the queue.
-        while self.queue and self.port.space_to_write_request():
-            msg = self.queue.pop(0)
-            self.port.write_request(msg)
-            work += 1
-        return work
-
-    def writeRequest(self, msg, notify=1):
-        if self.closed:
-            val = -1
-        elif self.writeReady():
-            self.port.write_request(msg)
-            if notify: self.notify()
-            val = 1
-        else:
-            self.queue.append(msg)
-            val = 0
-        return val
-
-    def writeResponse(self, msg):
-        if self.closed: return -1
-        self.port.write_response(msg)
-        return 1
-
-    def writeReady(self):
-        if self.closed or self.queue: return 0
-        return self.port.space_to_write_request()
-
-    def readRequest(self):
-        if self.closed:
-            return None
-        if self.port.request_to_read():
-            val = self.port.read_request()
-        else:
-            val = None
-        return val
-        
-    def readResponse(self):
-        if self.closed:
-            return None
-        if self.port.response_to_read():
-            val = self.port.read_response()
-        else:
-            val = None
-        return val
diff --git a/tools/xenmgr/lib/server/console.py b/tools/xenmgr/lib/server/console.py
deleted file mode 100755 (executable)
index f26a4dd..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-
-from twisted.internet import reactor
-from twisted.internet import protocol
-from twisted.protocols import telnet
-
-import xend.utils
-
-from xenmgr import EventServer
-eserver = EventServer.instance()
-
-import controller
-from messages import *
-from params import *
-
-"""Telnet binary option."""
-TRANSMIT_BINARY = '0'
-WILL = chr(251)
-IAC = chr(255)
-
-class ConsoleProtocol(protocol.Protocol):
-    """Asynchronous handler for a console TCP socket.
-    """
-
-    def __init__(self, controller, idx):
-        self.controller = controller
-        self.idx = idx
-        self.addr = None
-        self.binary = 0
-
-    def connectionMade(self):
-        peer = self.transport.getPeer()
-        self.addr = (peer.host, peer.port)
-        if self.controller.connect(self.addr, self):
-            self.transport.write("Cannot connect to console %d on domain %d\n"
-                                 % (self.idx, self.controller.dom))
-            self.loseConnection()
-            return
-        else:
-            self.transport.write("Connected to console %d on domain %d\n"
-                                 % (self.idx, self.controller.dom))
-            self.setTelnetTransmitBinary()
-            eserver.inject('xend.console.connect',
-                           [self.idx, self.addr[0], self.addr[1]])
-
-    def setTelnetTransmitBinary(self):
-        """Send the sequence to set the telnet TRANSMIT-BINARY option.
-        """
-        self.write(IAC + WILL + TRANSMIT_BINARY)
-
-    def dataReceived(self, data):
-        if self.controller.handleInput(self, data):
-            self.loseConnection()
-
-    def write(self, data):
-        #if not self.connected: return -1
-        self.transport.write(data)
-        return len(data)
-
-    def connectionLost(self, reason=None):
-        eserver.inject('xend.console.disconnect',
-                       [self.idx, self.addr[0], self.addr[1]])
-        self.controller.disconnect()
-
-    def loseConnection(self):
-        self.transport.loseConnection()
-
-class ConsoleFactory(protocol.ServerFactory):
-    """Asynchronous handler for a console server socket.
-    """
-    protocol = ConsoleProtocol
-    
-    def __init__(self, controller, idx):
-        #protocol.ServerFactory.__init__(self)
-        self.controller = controller
-        self.idx = idx
-
-    def buildProtocol(self, addr):
-        proto = self.protocol(self.controller, self.idx)
-        proto.factory = self
-        return proto
-
-class ConsoleControllerFactory(controller.ControllerFactory):
-    """Factory for creating console controllers.
-    """
-
-    def createInstance(self, dom, console_port=None):
-        if console_port is None:
-            console_port = CONSOLE_PORT_BASE + dom
-        console = ConsoleController(self, dom, console_port)
-        self.addInstance(console)
-        eserver.inject('xend.console.create',
-                       [console.idx, console.dom, console.console_port])
-        return console
-        
-    def consoleClosed(self, console):
-        eserver.inject('xend.console.close', console.idx)
-        self.delInstance(console)
-
-class ConsoleController(controller.Controller):
-    """Console controller for a domain.
-    Does not poll for i/o itself, but relies on the notifier to post console
-    output and the connected TCP sockets to post console input.
-    """
-
-    def __init__(self, factory, dom, console_port):
-        #print 'ConsoleController> dom=', dom, type(dom)
-        controller.Controller.__init__(self, factory, dom)
-        self.majorTypes = [ CMSG_CONSOLE ]
-        self.status = "new"
-        self.addr = None
-        self.conn = None
-        self.rbuf = xend.utils.buffer()
-        self.wbuf = xend.utils.buffer()
-        self.console_port = console_port
-
-        self.registerChannel()
-        self.listener = None
-        self.listen()
-        #print 'ConsoleController<', 'dom=', self.dom, 'idx=', self.idx
-
-    def sxpr(self):
-        val =['console',
-              ['status',       self.status ],
-              ['id',           self.idx ],
-              ['domain',       self.dom ],
-              ['local_port',   self.channel.getLocalPort() ],
-              ['remote_port',  self.channel.getRemotePort() ],
-              ['console_port', self.console_port ] ]
-        if self.addr:
-            val.append(['connected', self.addr[0], self.addr[1]])
-        return val
-
-    def ready(self):
-        return not (self.closed() or self.rbuf.empty())
-
-    def closed(self):
-        return self.status == 'closed'
-
-    def connected(self):
-        return self.status == 'connected'
-
-    def close(self):
-        try:
-            #print 'ConsoleController> close dom=', self.dom
-            self.status = "closed"
-            if self.conn:
-                self.conn.loseConnection()
-            self.listener.stopListening()
-            self.deregisterChannel()
-            self.lostChannel()
-        except Exception, ex:
-            print 'ConsoleController>close>', ex
-            raise
-
-    def listen(self):
-        """Listen for TCP connections to the console port..
-        """
-        if self.closed(): return
-        self.status = "listening"
-        if self.listener:
-            #self.listener.startListening()
-            pass
-        else:
-            f = ConsoleFactory(self, self.idx)
-            self.listener = reactor.listenTCP(self.console_port, f)
-
-    def connect(self, addr, conn):
-        if self.closed(): return -1
-        if self.connected(): return -1
-        self.addr = addr
-        self.conn = conn
-        self.status = "connected"
-        self.handleOutput()
-        return 0
-
-    def disconnect(self):
-        if self.conn:
-            self.conn.loseConnection()
-        self.addr = None
-        self.conn = None
-        self.listen()
-
-    def requestReceived(self, msg, type, subtype):
-        #print '***Console', self.dom, msg.get_payload()
-        self.rbuf.write(msg.get_payload())
-        self.handleOutput()
-        
-    def responseReceived(self, msg, type, subtype):
-        pass
-
-    def produceRequests(self):
-        # Send as much pending console data as there is room for.
-        work = 0
-        while not self.wbuf.empty() and self.channel.writeReady():
-            msg = xend.utils.message(CMSG_CONSOLE, 0, 0)
-            msg.append_payload(self.wbuf.read(msg.MAX_PAYLOAD))
-            work += self.channel.writeRequest(msg, notify=0)
-        return work
-
-    def handleInput(self, conn, data):
-        """Handle some external input aimed at the console.
-        Called from a TCP connection (conn).
-        """
-        if self.closed(): return -1
-        if conn != self.conn: return 0
-        self.wbuf.write(data)
-        if self.produceRequests():
-            self.channel.notify()
-        return 0
-
-    def handleOutput(self):
-        """Handle buffered output from the console.
-        Sends it to the connected console (if any).
-        """
-        if self.closed():
-            #print 'Console>handleOutput> closed'
-            return -1
-        if not self.conn:
-            #print 'Console>handleOutput> not connected'
-            return 0
-        while not self.rbuf.empty():
-            try:
-                #print 'Console>handleOutput> writing...'
-                bytes = self.conn.write(self.rbuf.peek())
-                if bytes > 0:
-                    self.rbuf.discard(bytes)
-            except socket.error, error:
-                pass
-        #print 'Console>handleOutput<'
-        return 0
diff --git a/tools/xenmgr/lib/server/controller.py b/tools/xenmgr/lib/server/controller.py
deleted file mode 100755 (executable)
index 900c2d5..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-from twisted.internet import defer
-
-import channel
-from messages import msgTypeName
-
-class CtrlMsgRcvr:
-    """Abstract class for things that deal with a control interface to a domain.
-    """
-
-
-    def __init__(self):
-        self.channelFactory = channel.channelFactory()
-        self.majorTypes = [ ]
-        self.subTypes = {}
-        self.dom = None
-        self.channel = None
-        self.idx = None
-
-    def requestReceived(self, msg, type, subtype):
-        method = self.subTypes.get(subtype)
-        if method:
-            method(msg, 1)
-        else:
-            print ('requestReceived> No handler: Message type %s %d:%d'
-                   % (msgTypeName(type, subtype), type, subtype)), self
-        
-    def responseReceived(self, msg, type, subtype):
-        method = self.subTypes.get(subtype)
-        if method:
-            method(msg, 0)
-        else:
-            print ('responseReceived> No handler: Message type %s %d:%d'
-                   % (msgTypeName(type, subtype), type, subtype)), self
-
-    def lostChannel(self):
-        pass
-    
-    def registerChannel(self):
-        #print 'CtrlMsgRcvr>registerChannel>', self
-        self.channel = self.channelFactory.domChannel(self.dom)
-        self.idx = self.channel.getIndex()
-        if self.majorTypes:
-            self.channel.registerDevice(self.majorTypes, self)
-        
-    def deregisterChannel(self):
-        #print 'CtrlMsgRcvr>deregisterChannel>', self
-        if self.channel:
-            self.channel.deregisterDevice(self)
-            del self.channel
-
-    def produceRequests(self):
-        return 0
-
-    def writeRequest(self, msg):
-        if self.channel:
-            self.channel.writeRequest(msg)
-        else:
-            print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self
-
-    def writeResponse(self, msg):
-        if self.channel:
-            self.channel.writeResponse(msg)
-        else:
-            print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self
-            
-class ControllerFactory(CtrlMsgRcvr):
-    """Abstract class for factories creating controllers.
-    Maintains a table of instances.
-    """
-
-    def __init__(self):
-        CtrlMsgRcvr.__init__(self)
-        self.instances = {}
-        self.dlist = []
-        self.dom = 0
-        # Timeout (in seconds) for deferreds.
-        self.timeout = 10
-        
-    def addInstance(self, instance):
-        self.instances[instance.idx] = instance
-
-    def getInstance(self, idx):
-        return self.instances.get(idx)
-
-    def getInstances(self):
-        return self.instances.values()
-
-    def getInstanceByDom(self, dom):
-        for inst in self.instances.values():
-            if inst.dom == dom:
-                return inst
-        return None
-
-    def delInstance(self, instance):
-        #print 'ControllerFactory>delInstance>', instance.idx
-        if instance.idx in self.instances:
-            #print 'ControllerFactory>delInstance> remove', instance.idx
-            del self.instances[instance.idx]
-
-    def createInstance(self, dom, recreate=0):
-        raise NotImplementedError()
-
-    def instanceClosed(self, instance):
-        #print 'ControllerFactory>instanceClosed>', instance.idx, instance
-        self.delInstance(instance)
-
-    def addDeferred(self):
-        d = defer.Deferred()
-        if self.timeout > 0:
-            # The deferred will error if not called before timeout.
-            d.setTimeout(self.timeout)
-        self.dlist.append(d)
-        return d
-
-    def callDeferred(self, *args):
-        if self.dlist:
-            d = self.dlist.pop(0)
-            d.callback(*args)
-
-    def errDeferred(self, *args):
-        if self.dlist:
-            d = self.dlist.pop(0)
-            d.errback(*args)
-
-class Controller(CtrlMsgRcvr):
-    """Abstract class for a device controller attached to a domain.
-    """
-
-    def __init__(self, factory, dom):
-        CtrlMsgRcvr.__init__(self)
-        self.factory = factory
-        self.dom = int(dom)
-        self.channel = None
-        self.idx = None
-
-    def close(self):
-        self.deregisterChannel()
-        self.lostChannel()
-
-    def lostChannel(self):
-        #print 'Controller>lostChannel>', self, self.factory
-        self.factory.instanceClosed(self)
-
-class Dev:
-
-    def __init__(self, controller):
-        self.controller = controller
-        self.props = {}
-
-    def setprop(self, k, v):
-        self.props[k] = v
-
-    def getprop(self, k, v=None):
-        return self.props.get(k, v)
-
-    def hasprop(self, k):
-        return k in self.props
-
-    def delprop(self, k):
-        if k in self.props:
-            del self.props[k]
-
-    #def __repr__(self):
-    #    return str(self.sxpr())
-
-    def sxpr(self):
-        raise NotImplementedError()
-
-    
diff --git a/tools/xenmgr/lib/server/cstruct.py b/tools/xenmgr/lib/server/cstruct.py
deleted file mode 100755 (executable)
index 880931b..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-import struct
-
-class Struct:
-
-    maxDepth = 10
-
-    base = ['x', 'B', 'H', 'I', 'L', 'Q', 'c', 'h', 'i', 'l', 'q', ]
-
-    sizes = {'B': 1,
-            'H': 2,
-            'I': 4,
-            'L': 4,
-            'Q': 8,
-            'c': 1,
-            'h': 2,
-            'i': 4,
-            'l': 4,
-            'q': 8,
-            'x': 1,
-            }
-
-    formats = {
-        'int8'          : 'B',
-        'int16'         : 'H',
-        'int32'         : 'I',
-        'int64'         : 'Q',
-        'u8'            : 'B',
-        'u16'           : 'H',
-        'u32'           : 'I',
-        'u64'           : 'Q'
-        }
-
-    def typedef(self, name, val):
-        self.formats[name] = val
-
-    def struct(self, name, *f):
-        self.typedef(name, StructInfo(self, f))
-        
-    def getType(self, name):
-        return self.formats[name]
-
-    def format(self, ty):
-        d = 0
-        f = ty
-        while d < self.maxDepth:
-            d += 1
-            f = self.formats[f]
-            if isinstance(f, StructInfo):
-                return f.format()
-            if f in self.base:
-                return f
-        return -1
-
-    def alignedformat(self, ty):
-        fmt = self.format(ty)
-        #print 'alignedformat> %s |%s|' %(ty, fmt)
-        afmt = self.align(fmt)
-        #print 'alignedformat< %s |%s| |%s|' % (ty, fmt, afmt)
-        return afmt
-
-    def align(self, fmt):
-        n1 = 0
-        afmt = ''
-        for a in fmt:
-            n2 = self.getSize(a)
-            m = n1 % n2
-            if m:
-                d = (n2 - m)
-                afmt += 'x' * d
-                n1 += d
-            afmt += a
-            n1 += n2
-        return afmt
-
-    def fmtsize(self, fmt):
-        s = 0
-        for f in fmt:
-            s += self.getSize(f)
-        return s
-
-    def getSize(self, f):
-        return self.sizes[f]
-
-    def pack(self, ty, data):
-        return self.getType(ty).pack(data)
-
-    def unpack(self, ty, data):
-        return self.getType(ty).unpack(data)
-
-    def show(self):
-        l = self.formats.keys()
-        l.sort()
-        for v in l:
-            print "%-35s %-10s %s" % (v, self.format(v), self.alignedformat(v))
-
-
-class StructInfo:
-
-    def __init__(self, s, f):
-        self.fmt = None
-        self.structs = s
-        self.fields = f
-
-    def alignedformat(self):
-        if self.afmt: return self.afmt
-        self.afmt = self.structs.align(self.format())
-        return self.afmt
-    
-    def format(self):
-        if self.fmt: return self.fmt
-        fmt = ""
-        for (ty, name) in self.fields:
-            fmt += self.formatString(ty)
-        self.fmt = fmt
-        return fmt
-
-    def formatString(self, ty):
-        if ty in self.fields:
-            ty = self.fields[ty]
-        return self.structs.format(ty)
-
-    def pack(self, *args):
-        return struct.pack(self.alignedformat(), *args)
-
-    def unpack(self, data):
-        return struct.unpack(self.alignedformat(), data)
-
-types = Struct()
-
-types.typedef('short'         , 'h')
-types.typedef('int'           , 'i')
-types.typedef('long'          , 'l')
-types.typedef('unsigned short', 'H')
-types.typedef('unsigned int'  , 'I')
-types.typedef('unsigned long' , 'L')
-types.typedef('domid_t'       , 'u64')
-types.typedef('blkif_vdev_t'  , 'u16')
-types.typedef('blkif_pdev_t'  , 'u16')
-types.typedef('blkif_sector_t', 'u64')
-
-types.struct('u8[6]',
-             ('u8', 'a1'),
-             ('u8', 'a2'),
-             ('u8', 'a3'),
-             ('u8', 'a4'),
-             ('u8', 'a5'),
-             ('u8', 'a6'))
-             
-types.struct('blkif_fe_interface_status_changed_t',
-    ('unsigned int',    'handle'),
-    ('unsigned int',    'status'),
-    ('unsigned int',    'evtchn'))
-
-types.struct('blkif_fe_driver_status_changed_t',
-    ('unsigned int',    'status'),
-    ('unsigned int',    'nr_interfaces'))
-
-types.struct('blkif_fe_interface_connect_t',
-    ('unsigned int' ,   'handle'),
-    ('unsigned long',   'shmem_frame'))
-
-types.struct('blkif_fe_interface_disconnect_t',
-    ('unsigned int',   'handle'))
-
-types.struct('blkif_extent_t',
-    ('blkif_pdev_t'  , 'device'),
-    ('blkif_sector_t', 'sector_start'),
-    ('blkif_sector_t', 'sector_length'))
-
-types.struct('blkif_be_create_t', 
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'blkif_handle'),
-    ('unsigned int',   'status'))
-             
-types.struct('blkif_be_destroy_t',
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'blkif_handle'),
-    ('unsigned int',   'status'))
-
-types.struct('blkif_be_connect_t',
-    ('domid_t'      ,  'domid'),
-    ('unsigned int' ,  'blkif_handle'),
-    ('unsigned int' ,  'evtchn'),
-    ('unsigned long',  'shmem_frame'),
-    ('unsigned int' ,  'status'))
-
-types.struct('blkif_be_disconnect_t',
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'blkif_handle'),
-    ('unsigned int',   'status'))
-
-types.struct('blkif_be_vbd_create_t', 
-    ('domid_t'     ,   'domid'),         #Q
-    ('unsigned int',   'blkif_handle'),  #I
-    ('blkif_vdev_t',   'vdevice'),       #H
-    ('int'         ,   'readonly'),      #i
-    ('unsigned int',   'status'))        #I
-
-types.struct('blkif_be_vbd_destroy_t', 
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'blkif_handle'),
-    ('blkif_vdev_t',   'vdevice'),
-    ('unsigned int',   'status'))
-
-types.struct('blkif_be_vbd_grow_t', 
-    ('domid_t'       , 'domid'),         #Q
-    ('unsigned int'  , 'blkif_handle'),  #I
-    ('blkif_vdev_t'  , 'vdevice'),       #H   
-    ('blkif_extent_t', 'extent'),        #HQQ
-    ('unsigned int'  , 'status'))        #I
-
-types.struct('blkif_be_vbd_shrink_t', 
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'blkif_handle'),
-    ('blkif_vdev_t',   'vdevice'),
-    ('unsigned int',   'status'))
-
-types.struct('blkif_be_driver_status_changed_t',
-    ('unsigned int',   'status'),
-    ('unsigned int',   'nr_interfaces'))
-
-types.struct('netif_fe_interface_status_changed_t',
-    ('unsigned int',   'handle'),
-    ('unsigned int',   'status'),
-    ('unsigned int',   'evtchn'),
-    ('u8[6]',          'mac'))
-
-types.struct('netif_fe_driver_status_changed_t',
-    ('unsigned int',   'status'),
-    ('unsigned int',   'nr_interfaces'))
-
-types.struct('netif_fe_interface_connect_t',
-    ('unsigned int',   'handle'),
-    ('unsigned long',  'tx_shmem_frame'),
-    ('unsigned long',  'rx_shmem_frame'))
-
-types.struct('netif_fe_interface_disconnect_t',
-    ('unsigned int',   'handle'))
-
-types.struct('netif_be_create_t', 
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'netif_handle'),
-    ('u8[6]'       ,   'mac'),
-    ('unsigned int',   'status'))
-
-types.struct('netif_be_destroy_t',
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'netif_handle'),
-    ('unsigned int',   'status'))
-
-types.struct('netif_be_connect_t', 
-    ('domid_t'      ,  'domid'),
-    ('unsigned int' ,  'netif_handle'),
-    ('unsigned int' ,  'evtchn'),
-    ('unsigned long',  'tx_shmem_frame'),
-    ('unsigned long',  'rx_shmem_frame'),
-    ('unsigned int' ,  'status'))
-
-types.struct('netif_be_disconnect_t',
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'netif_handle'),
-    ('unsigned int',   'status'))
-
-types.struct('netif_be_driver_status_changed_t',
-    ('unsigned int',   'status'),
-    ('unsigned int',   'nr_interfaces'))
-
-if 1 or __name__ == "__main__":
-    types.show()
diff --git a/tools/xenmgr/lib/server/domain.py b/tools/xenmgr/lib/server/domain.py
deleted file mode 100644 (file)
index ab22234..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-import channel
-import controller
-from messages import *
-
-class DomainControllerFactory(controller.ControllerFactory):
-    """Factory for creating domain controllers.
-    """
-
-    def createInstance(self, dom):
-        d = DomainController(self, dom)
-        self.addInstance(d)
-        return d
-    
-    def getInstanceByDom(self, dom):
-        for inst in self.instances.values():
-            if inst.dom == dom:
-                return inst
-        inst = self.createInstance(dom)
-        return inst
-
-
-class DomainController(controller.Controller):
-    """Generic controller for a domain.
-    """
-
-    reasons = {'poweroff' : 'shutdown_poweroff_t',
-               'reboot'   : 'shutdown_reboot_t',
-               'suspend'  : 'shutdown_suspend_t' }
-
-    def __init__(self, factory, dom):
-        controller.Controller.__init__(self, factory, dom)
-        self.majorTypes = [ CMSG_SHUTDOWN ]
-        self.registerChannel()
-        print 'DomainController>', self, self.channel, self.idx
-
-    def shutdown(self, reason):
-        msgtype = self.reasons.get(reason)
-        if not msgtype:
-            raise ValueError('invalid reason:' + reason)
-        msg = packMsg(msgtype, {})
-        self.writeRequest(msg)
diff --git a/tools/xenmgr/lib/server/messages.py b/tools/xenmgr/lib/server/messages.py
deleted file mode 100644 (file)
index f920bd6..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-import struct
-
-import xend.utils
-
-DEBUG = 0
-
-""" All message formats.
-Added to incrementally for the various message types.
-See below.
-"""
-msg_formats = {}
-
-#============================================================================
-# Console message types.
-#============================================================================
-
-CMSG_CONSOLE  = 0
-
-console_formats = { 'console_data': (CMSG_CONSOLE, 0) }
-
-msg_formats.update(console_formats)
-
-#============================================================================
-# Block interface message types.
-#============================================================================
-
-CMSG_BLKIF_BE = 1
-CMSG_BLKIF_FE = 2
-
-CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
-CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
-CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
-CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
-
-CMSG_BLKIF_BE_CREATE      = 0
-CMSG_BLKIF_BE_DESTROY     = 1
-CMSG_BLKIF_BE_CONNECT     = 2
-CMSG_BLKIF_BE_DISCONNECT  = 3
-CMSG_BLKIF_BE_VBD_CREATE  = 4
-CMSG_BLKIF_BE_VBD_DESTROY = 5
-CMSG_BLKIF_BE_VBD_GROW    = 6
-CMSG_BLKIF_BE_VBD_SHRINK  = 7
-CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED    = 32
-
-BLKIF_DRIVER_STATUS_DOWN  = 0
-BLKIF_DRIVER_STATUS_UP    = 1
-
-BLKIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
-BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
-BLKIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
-
-BLKIF_BE_STATUS_OKAY                = 0
-BLKIF_BE_STATUS_ERROR               = 1
-BLKIF_BE_STATUS_INTERFACE_EXISTS    = 2
-BLKIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
-BLKIF_BE_STATUS_INTERFACE_CONNECTED = 4
-BLKIF_BE_STATUS_VBD_EXISTS          = 5
-BLKIF_BE_STATUS_VBD_NOT_FOUND       = 6
-BLKIF_BE_STATUS_OUT_OF_MEMORY       = 7
-BLKIF_BE_STATUS_EXTENT_NOT_FOUND    = 8
-BLKIF_BE_STATUS_MAPPING_ERROR       = 9
-
-blkif_formats = {
-    'blkif_be_connect_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT),
-
-    'blkif_be_create_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE),
-
-    'blkif_be_disconnect_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT),
-
-    'blkif_be_destroy_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY),
-
-    'blkif_be_vbd_create_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE),
-
-    'blkif_be_vbd_grow_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW),
-
-    'blkif_be_vbd_destroy_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY),
-
-    'blkif_fe_interface_status_changed_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED),
-
-    'blkif_fe_driver_status_changed_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED),
-
-    'blkif_fe_interface_connect_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT),
-}
-
-msg_formats.update(blkif_formats)
-
-#============================================================================
-# Network interface message types.
-#============================================================================
-
-CMSG_NETIF_BE = 3
-CMSG_NETIF_FE = 4
-
-CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED =  0
-CMSG_NETIF_FE_DRIVER_STATUS_CHANGED    = 32
-CMSG_NETIF_FE_INTERFACE_CONNECT        = 33
-CMSG_NETIF_FE_INTERFACE_DISCONNECT     = 34
-
-CMSG_NETIF_BE_CREATE      = 0
-CMSG_NETIF_BE_DESTROY     = 1
-CMSG_NETIF_BE_CONNECT     = 2
-CMSG_NETIF_BE_DISCONNECT  = 3
-CMSG_NETIF_BE_DRIVER_STATUS_CHANGED    = 32
-
-NETIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
-NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
-NETIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
-
-NETIF_DRIVER_STATUS_DOWN   = 0
-NETIF_DRIVER_STATUS_UP     = 1
-
-netif_formats = {
-    'netif_be_connect_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT),
-
-    'netif_be_create_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE),
-
-    'netif_be_disconnect_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT),
-
-    'netif_be_destroy_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY),
-
-    'netif_be_driver_status_changed_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED),
-
-    'netif_fe_driver_status_changed_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED),
-
-    'netif_fe_interface_connect_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT),
-
-    'netif_fe_interface_status_changed_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED),
-    }
-
-msg_formats.update(netif_formats)
-
-#============================================================================
-CMSG_SHUTDOWN = 6
-
-CMSG_SHUTDOWN_POWEROFF  = 0
-CMSG_SHUTDOWN_REBOOT    = 1
-CMSG_SHUTDOWN_SUSPEND   = 2
-
-STOPCODE_shutdown       = 0
-STOPCODE_reboot         = 1
-STOPCODE_suspend        = 2
-
-shutdown_formats = {
-    'shutdown_poweroff_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_POWEROFF),
-    
-    'shutdown_reboot_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_REBOOT),
-
-    'shutdown_suspend_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SUSPEND),
-    }
-
-msg_formats.update(shutdown_formats)
-
-#============================================================================
-
-class Msg:
-    pass
-
-def packMsg(ty, params):
-    if DEBUG: print '>packMsg', ty, params
-    (major, minor) = msg_formats[ty]
-    args = {}
-    for (k, v) in params.items():
-        if k == 'mac':
-            for i in range(0, 6):
-                args['mac[%d]' % i] = v[i]
-        else:
-            args[k] = v
-    if DEBUG:
-        for (k, v) in args.items():
-            print 'packMsg>', k, v, type(v)
-    msgid = 0
-    msg = xend.utils.message(major, minor, msgid, args)
-    return msg
-
-def unpackMsg(ty, msg):
-    args = msg.get_payload()
-    mac = [0, 0, 0, 0, 0, 0]
-    macs = []
-    for (k, v) in args.items():
-        if k.startswith('mac['):
-            macs += k
-            i = int(k[4:5])
-            mac[i] = v
-        else:
-            pass
-    if macs:
-        args['mac'] = mac
-        for k in macs:
-            del args[k]
-    if DEBUG: print '<unpackMsg', ty, args
-    return args
-
-def msgTypeName(ty, subty):
-    for (name, info) in msg_formats.items():
-        if info[0] == ty and info[1] == subty:
-            return name
-    return None
-
diff --git a/tools/xenmgr/lib/server/netif.py b/tools/xenmgr/lib/server/netif.py
deleted file mode 100755 (executable)
index cb7496c..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-import random
-
-from twisted.internet import defer
-
-from xenmgr import sxp
-from xenmgr import PrettyPrint
-from xenmgr import XendBridge
-
-import channel
-import controller
-from messages import *
-
-class NetifControllerFactory(controller.ControllerFactory):
-    """Factory for creating network interface controllers.
-    Also handles the 'back-end' channel to the device driver domain.
-    """
-
-    def __init__(self):
-        controller.ControllerFactory.__init__(self)
-
-        self.majorTypes = [ CMSG_NETIF_BE ]
-
-        self.subTypes = {
-            CMSG_NETIF_BE_CREATE : self.recv_be_create,
-            CMSG_NETIF_BE_CONNECT: self.recv_be_connect,
-            CMSG_NETIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
-            }
-        self.attached = 1
-        self.registerChannel()
-
-    def createInstance(self, dom, recreate=0):
-        """Create or find the network interface controller for a domain.
-        """
-        #print 'netif>createInstance> dom=', dom
-        netif = self.getInstanceByDom(dom)
-        if netif is None:
-            netif = NetifController(self, dom)
-            self.addInstance(netif)
-        return netif
-
-    def getDomainDevices(self, dom):
-        netif = self.getInstanceByDom(dom)
-        return (netif and netif.getDevices()) or []
-
-    def getDomainDevice(self, dom, vif):
-        netif = self.getInstanceByDom(dom)
-        return (netif and netif.getDevice(vif)) or None
-        
-    def setControlDomain(self, dom, recreate=0):
-        """Set the 'back-end' device driver domain.
-        """
-        if self.dom == dom: return
-        self.deregisterChannel()
-        if not recreate:
-            self.attached = 0
-        self.dom = dom
-        self.registerChannel()
-        #
-        #if xend.netif.be_port.remote_dom != 0:
-        #    xend.netif.recovery = True
-        #    xend.netif.be_port = xend.main.port_from_dom(dom)
-        #
-
-    def getControlDomain(self):
-        return self.dom
-
-    def recv_be_create(self, msg, req):
-        self.callDeferred(0)
-    
-    def recv_be_connect(self, msg, req):
-        val = unpackMsg('netif_be_connect_t', msg)
-        dom = val['domid']
-        vif = val['netif_handle']
-        netif = self.getInstanceByDom(dom)
-        if netif:
-            netif.send_interface_connected(vif)
-        else:
-            print "recv_be_connect> unknown vif=", vif
-            pass
-
-    def recv_be_driver_status_changed(self, msg, req):
-        val = unpackMsg('netif_be_driver_status_changed_t', msg)
-        status = val['status']
-        if status == NETIF_DRIVER_STATUS_UP and not self.attached:
-            # If we are not attached the driver domain was changed, and
-            # this signals the new driver domain is ready.
-            for netif in self.getInstances():
-                netif.reattach_devices()
-            self.attached = 1
-
-##         pl = msg.get_payload()
-##         status = pl['status']
-##         if status == NETIF_DRIVER_STATUS_UP:
-##             if xend.netif.recovery:
-##                 print "New netif backend now UP, notifying guests:"
-##                 for netif_key in interface.list.keys():
-##                     netif = interface.list[netif_key]
-##                     netif.create()
-##                     print "  Notifying %d" % netif.dom
-##                     msg = xend.utils.message(
-##                         CMSG_NETIF_FE,
-##                         CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
-##                         { 'handle' : 0, 'status' : 1 })
-##                     netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom),msg)
-##                 print "Done notifying guests"
-##                 recovery = False
-                
-class NetDev(controller.Dev):
-    """Info record for a network device.
-    """
-
-    def __init__(self, ctrl, vif, mac):
-        controller.Dev.__init__(self, ctrl)
-        self.vif = vif
-        self.mac = mac
-        self.evtchn = None
-        self.bridge = None
-
-    def sxpr(self):
-        vif = str(self.vif)
-        mac = ':'.join(map(lambda x: "%x" % x, self.mac))
-        val = ['netdev', ['vif', vif], ['mac', mac]]
-        if self.bridge:
-            val.append(['bridge', self.bridge])
-        if self.evtchn:
-            val.append(['evtchn',
-                        self.evtchn['port1'],
-                        self.evtchn['port2']])
-        return val
-
-    def bridge_add(self, bridge):
-        self.bridge = XendBridge.vif_bridge_add(self.controller.dom, self.vif, bridge)
-
-    def bridge_rem(self):
-        if not self.bridge: return
-        XendBridge.vif_bridge_rem(self.controller.dom, self.vif, self.bridge)
-        self.bridge = None
-
-    def destroy(self):
-        def cb_destroy(val):
-            self.controller.send_be_destroy(self.vif)
-        print 'NetDev>destroy>', 'vif=', self.vif
-        PrettyPrint.prettyprint(self.sxpr())
-        self.bridge_rem()
-        d = self.controller.factory.addDeferred()
-        d.addCallback(cb_destroy)
-        self.controller.send_be_disconnect(self.vif)
-        #self.controller.send_be_destroy(self.vif)
-        
-
-class NetifController(controller.Controller):
-    """Network interface controller. Handles all network devices for a domain.
-    """
-    
-    def __init__(self, factory, dom):
-        #print 'NetifController> dom=', dom
-        controller.Controller.__init__(self, factory, dom)
-        self.devices = {}
-        
-        self.majorTypes = [ CMSG_NETIF_FE ]
-
-        self.subTypes = {
-            CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
-                self.recv_fe_driver_status_changed,
-            CMSG_NETIF_FE_INTERFACE_CONNECT    :
-                self.recv_fe_interface_connect,
-            }
-        self.registerChannel()
-        #print 'NetifController<', 'dom=', self.dom, 'idx=', self.idx
-
-    def sxpr(self):
-        val = ['netif', ['dom', self.dom]]
-        return val
-    
-    def randomMAC(self):
-        # VIFs get a random MAC address with a "special" vendor id.
-        # 
-        # NB. The vendor is currently an "obsolete" one that used to belong
-        # to DEC (AA-00-00). Using it is probably a bit rude :-)
-        # 
-        # NB2. The first bit of the first random octet is set to zero for
-        # all dynamic MAC addresses. This may allow us to manually specify
-        # MAC addresses for some VIFs with no fear of clashes.
-        mac = [ 0xaa, 0x00, 0x00,
-                random.randint(0x00, 0x7f),
-                random.randint(0x00, 0xff),
-                random.randint(0x00, 0xff) ]
-        return mac
-
-    def lostChannel(self):
-        print 'NetifController>lostChannel>', 'dom=', self.dom
-        #self.destroyDevices()
-        controller.Controller.lostChannel(self)
-
-    def getDevices(self):
-        return self.devices.values()
-
-    def getDevice(self, vif):
-        return self.devices.get(vif)
-
-    def addDevice(self, vif, vmac):
-        if vmac is None:
-            mac = self.randomMAC()
-        else:
-            mac = [ int(x, 16) for x in vmac.split(':') ]
-        if len(mac) != 6: raise ValueError("invalid mac")
-        #print "attach_device>", "vif=", vif, "mac=", mac
-        dev = NetDev(self, vif, mac)
-        self.devices[vif] = dev
-        return dev
-
-    def destroy(self):
-        print 'NetifController>destroy>', 'dom=', self.dom
-        self.destroyDevices()
-        
-    def destroyDevices(self):
-        for dev in self.getDevices():
-            dev.destroy()
-
-    def attachDevice(self, vif, vmac, recreate=0):
-        """Attach a network device.
-        If vmac is None a random mac address is assigned.
-
-        @param vif interface index
-        @param vmac mac address (string)
-        """
-        self.addDevice(vif, vmac)
-        if recreate:
-            d = defer.Deferred()
-            d.callback(self)
-        else:
-            d = self.factory.addDeferred()
-            self.send_be_create(vif)
-        return d
-
-    def reattach_devices(self):
-        """Reattach all devices when the back-end control domain has changed.
-        """
-        d = self.factory.addDeferred()
-        self.send_be_create(vif)
-        self.attach_fe_devices(0)
-
-    def attach_fe_devices(self):
-        for dev in self.devices.values():
-            msg = packMsg('netif_fe_interface_status_changed_t',
-                          { 'handle' : dev.vif,
-                            'status' : NETIF_INTERFACE_STATUS_DISCONNECTED,
-                            'evtchn' : 0,
-                            'mac'    : dev.mac })
-            self.writeRequest(msg)
-    
-    def recv_fe_driver_status_changed(self, msg, req):
-        if not req: return
-        msg = packMsg('netif_fe_driver_status_changed_t',
-                      { 'status'        : NETIF_DRIVER_STATUS_UP,
-                        'nr_interfaces' : len(self.devices) })
-        self.writeRequest(msg)
-        self.attach_fe_devices()
-
-    def recv_fe_interface_connect(self, msg, req):
-        val = unpackMsg('netif_fe_interface_connect_t', msg)
-        dev = self.devices[val['handle']]
-        dev.evtchn = channel.eventChannel(0, self.dom)
-        msg = packMsg('netif_be_connect_t',
-                      { 'domid'          : self.dom,
-                        'netif_handle'   : dev.vif,
-                        'evtchn'         : dev.evtchn['port1'],
-                        'tx_shmem_frame' : val['tx_shmem_frame'],
-                        'rx_shmem_frame' : val['rx_shmem_frame'] })
-        self.factory.writeRequest(msg)
-
-    def send_interface_connected(self, vif):
-        dev = self.devices[vif]
-        msg = packMsg('netif_fe_interface_status_changed_t',
-                      { 'handle' : dev.vif,
-                        'status' : NETIF_INTERFACE_STATUS_CONNECTED,
-                        'evtchn' : dev.evtchn['port2'],
-                        'mac'    : dev.mac })
-        self.writeRequest(msg)
-
-    def send_be_create(self, vif):
-        dev = self.devices[vif]
-        msg = packMsg('netif_be_create_t',
-                      { 'domid'        : self.dom,
-                        'netif_handle' : dev.vif,
-                        'mac'          : dev.mac })
-        self.factory.writeRequest(msg)
-
-    def send_be_disconnect(self, vif):
-        dev = self.devices[vif]
-        msg = packMsg('netif_be_disconnect_t',
-                      { 'domid'        : self.dom,
-                        'netif_handle' : dev.vif })
-        self.factory.writeRequest(msg)
-
-    def send_be_destroy(self, vif):
-        print 'NetifController>send_be_destroy>', 'dom=', self.dom, 'vif=', vif
-        PrettyPrint.prettyprint(self.sxpr())
-        dev = self.devices[vif]
-        del self.devices[vif]
-        msg = packMsg('netif_be_destroy_t',
-                      { 'domid'        : self.dom,
-                        'netif_handle' : vif })
-        self.factory.writeRequest(msg)
diff --git a/tools/xenmgr/lib/server/params.py b/tools/xenmgr/lib/server/params.py
deleted file mode 100644 (file)
index d8f064c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# The following parameters could be placed in a configuration file.
-PID_FILE  = '/var/run/xend.pid'
-LOG_FILE  = '/var/log/xend.log'
-USER = 'root'
-CONTROL_DIR  = '/var/run/xend'
-MGMT_SOCK    = 'xenmgrsock' # relative to CONTROL_DIR
-EVENT_PORT = 8001
-
-CONSOLE_PORT_BASE = 9600
-
diff --git a/tools/xenmgr/lib/sxp.py b/tools/xenmgr/lib/sxp.py
deleted file mode 100644 (file)
index dd4fece..0000000
+++ /dev/null
@@ -1,557 +0,0 @@
-#!/usr/bin/python2
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""
-Input-driven parsing for s-expression (sxp) format.
-Create a parser: pin = Parser();
-Then call pin.input(buf) with your input.
-Call pin.input_eof() when done.
-Use pin.read() to see if a value has been parsed, pin.get_val()
-to get a parsed value. You can call ready and get_val at any time -
-you don't have to wait until after calling input_eof.
-
-"""
-from __future__ import generators
-
-import sys
-import types
-import errno
-import string
-
-__all__ = [
-    "mime_type", 
-    "ParseError", 
-    "Parser", 
-    "atomp", 
-    "show", 
-    "show_xml", 
-    "elementp", 
-    "name", 
-    "attributes", 
-    "attribute", 
-    "children", 
-    "child", 
-    "child_at", 
-    "child0", 
-    "child1", 
-    "child2", 
-    "child3", 
-    "child4", 
-    "child_value", 
-    "has_id", 
-    "with_id", 
-    "child_with_id", 
-    "elements", 
-    "parse", 
-    ]
-
-mime_type = "application/sxp"
-
-escapes = {
-    'a': '\a',
-    'b': '\b',
-    't': '\t',
-    'n': '\n',
-    'v': '\v',
-    'f': '\f',
-    'r': '\r',
-    '\\': '\\',
-    '\'': '\'',
-    '\"': '\"'}
-
-k_list_open  = "("
-k_list_close = ")"
-k_attr_open  = "@"
-k_eval       = "!"
-
-escapes_rev = {}
-for k in escapes:
-    escapes_rev[escapes[k]] = k
-
-class ParseError(StandardError):
-
-    def __init__(self, parser, value):
-        self.parser = parser
-        self.value = value
-
-    def __str__(self):
-        return self.value
-
-class ParserState:
-
-    def __init__(self, fn, parent=None):
-        self.parent = parent
-        self.buf = ''
-        self.val = []
-        self.delim = None
-        self.fn = fn
-
-    def push(self, fn):
-        return ParserState(fn, parent=self)
-    
-class Parser:
-
-    def __init__(self):
-        self.error = sys.stderr
-        self.reset()
-
-    def reset(self):
-        self.val = []
-        self.eof = 0
-        self.err = 0
-        self.line_no = 0
-        self.char_no = 0
-        self.state = None
-
-    def push_state(self, fn):
-        self.state = self.state.push(fn)
-
-    def pop_state(self):
-        val = self.state
-        self.state = self.state.parent
-        if self.state and self.state.fn == self.state_start:
-            # Return to start state - produce the value.
-            self.val += self.state.val
-            self.state.val = []
-        return val
-
-    def in_class(self, c, s):
-        return s.find(c) >= 0
-        
-    def in_space_class(self, c):
-        return self.in_class(c, ' \t\n\v\f\r')
-
-    def is_separator(self, c):
-        return self.in_class(c, '{}()<>[]!;')
-
-    def in_comment_class(self, c):
-        return self.in_class(c, '#')
-
-    def in_string_quote_class(self, c):
-        return self.in_class(c, '"\'')
-
-    def in_printable_class(self, c):
-        return self.in_class(c, string.printable)
-
-    def set_error_stream(self, error):
-        self.error = error
-
-    def has_error(self):
-        return self.err > 0
-
-    def at_eof(self):
-        return self.eof
-
-    def input_eof(self):
-        self.eof = 1
-        self.input_char(-1)
-
-    def input(self, buf):
-        if not buf or len(buf) == 0:
-            self.input_eof()
-        else:
-            for c in buf:
-                self.input_char(c)
-
-    def input_char(self, c):
-        if self.at_eof():
-            pass
-        elif c == '\n':
-            self.line_no += 1
-            self.char_no = 0
-        else:
-           self.char_no += 1 
-
-        if self.state is None:
-            self.begin_start(None)
-        self.state.fn(c)
-
-    def ready(self):
-        return len(self.val) > 0
-
-    def get_val(self):
-        v = self.val[0]
-        self.val = self.val[1:]
-        return v
-
-    def get_all(self):
-        return self.val
-
-    def begin_start(self, c):
-        self.state = ParserState(self.state_start)
-
-    def end_start(self):
-        self.val += self.state.val
-        self.pop_state()
-    
-    def state_start(self, c):
-        if self.at_eof():
-            self.end_start()
-        elif self.in_space_class(c):
-            pass
-        elif self.in_comment_class(c):
-            self.begin_comment(c)
-        elif c == k_list_open:
-            self.begin_list(c)
-        elif c == k_list_close:
-            raise ParseError(self, "syntax error: "+c)
-        elif self.in_string_quote_class(c):
-            self.begin_string(c)
-        elif self.in_printable_class(c):
-            self.begin_atom(c)
-        elif c == chr(4):
-            # ctrl-D, EOT: end-of-text.
-            self.input_eof()
-        else:
-            raise ParseError(self, "invalid character: code %d" % ord(c))
-
-    def begin_comment(self, c):
-        self.push_state(self.state_comment)
-        self.state.buf += c
-
-    def end_comment(self):
-        self.pop_state()
-    
-    def state_comment(self, c):
-        if c == '\n' or self.at_eof():
-            self.end_comment()
-        else:
-            self.state.buf += c
-
-    def begin_string(self, c):
-        self.push_state(self.state_string)
-        self.state.delim = c
-
-    def end_string(self):
-        val = self.state.buf
-        self.state.parent.val.append(val)
-        self.pop_state()
-        
-    def state_string(self, c):
-        if self.at_eof():
-            raise ParseError(self, "unexpected EOF")
-        elif c == self.state.delim:
-            self.end_string()
-        elif c == '\\':
-            self.push_state(self.state_escape)
-        else:
-            self.state.buf += c
-
-    def state_escape(self, c):
-        if self.at_eof():
-            raise ParseError(self, "unexpected EOF")
-        d = escapes.get(c)
-        if d:
-            self.state.parent.buf += d
-            self.pop_state()
-        elif c == 'x':
-            self.state.fn = self.state_hex
-            self.state.val = 0
-        else:
-            self.state.fn = self.state_octal
-            self.state.val = 0
-            self.input_char(c)
-
-    def state_octal(self, c):
-        def octaldigit(c):
-            self.state.val *= 8
-            self.state.val += ord(c) - ord('0')
-            self.state.buf += c
-            if self.state.val < 0 or self.state.val > 0xff:
-                raise ParseError(self, "invalid octal escape: out of range " + self.state.buf)
-            if len(self.state.buf) == 3:
-               octaldone()
-               
-        def octaldone():
-            d = chr(self.state.val)
-            self.state.parent.buf += d
-            self.pop_state()
-            
-        if self.at_eof():
-            raise ParseError(self, "unexpected EOF")
-        elif '0' <= c <= '7':
-            octaldigit(c)
-        elif len(self.buf):
-            octaldone()
-            self.input_char(c)
-
-    def state_hex(self, c):
-        def hexdone():
-            d = chr(self.state.val)
-            self.state.parent.buf += d
-            self.pop_state()
-            
-        def hexdigit(c, d):
-            self.state.val *= 16
-            self.state.val += ord(c) - ord(d)
-            self.state.buf += c
-            if self.state.val < 0 or self.state.val > 0xff:
-                raise ParseError(self, "invalid hex escape: out of range " + self.state.buf)
-            if len(self.state.buf) == 2:
-                hexdone()
-            
-        if self.at_eof():
-            raise ParseError(self, "unexpected EOF")
-        elif '0' <= c <= '9':
-            hexdigit(c, '0')
-        elif 'A' <= c <= 'F':
-            hexdigit(c, 'A')
-        elif 'a' <= c <= 'f':
-            hexdigit(c, 'a')
-        elif len(buf):
-            hexdone()
-            self.input_char(c)
-
-    def begin_atom(self, c):
-        self.push_state(self.state_atom)
-        self.state.buf = c
-
-    def end_atom(self):
-        val = self.state.buf
-        self.state.parent.val.append(val)
-        self.pop_state()
-    
-    def state_atom(self, c):
-        if self.at_eof():
-            self.end_atom()
-        elif (self.is_separator(c) or
-              self.in_space_class(c) or
-              self.in_comment_class(c)):
-            self.end_atom()
-            self.input_char(c)
-        else:
-            self.state.buf += c
-
-    def begin_list(self, c):
-        self.push_state(self.state_list)
-
-    def end_list(self):
-        val = self.state.val
-        self.state.parent.val.append(val)
-        self.pop_state()
-
-    def state_list(self, c):
-        if self.at_eof():
-            raise ParseError(self, "unexpected EOF")
-        elif c == k_list_close:
-            self.end_list()
-        else:
-            self.state_start(c)
-
-def atomp(sxpr):
-    if sxpr.isalnum() or sxpr == '@':
-        return 1
-    for c in sxpr:
-        if c in string.whitespace: return 0
-        if c in '"\'\\(){}[]<>$#&%^': return 0
-        if c in string.ascii_letters: continue
-        if c in string.digits: continue
-        if c in '.-_:/~': continue
-        return 0
-    return 1
-    
-def show(sxpr, out=sys.stdout):
-    if isinstance(sxpr, types.ListType):
-        out.write(k_list_open)
-        i = 0
-        for x in sxpr:
-            if i: out.write(' ')
-            show(x, out)
-            i += 1
-        out.write(k_list_close)
-    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
-        out.write(sxpr)
-    else:
-        #out.write("'" + str(sxpr) + "'")
-        out.write(repr(str(sxpr)))
-
-def show_xml(sxpr, out=sys.stdout):
-    if isinstance(sxpr, types.ListType):
-        element = name(sxpr)
-        out.write('<%s' % element)
-        for attr in attributes(sxpr):
-            out.write(' %s=%s' % (attr[0], attr[1]))
-        out.write('>')
-        i = 0
-        for x in children(sxpr):
-            if i: out.write(' ')
-            show_xml(x, out)
-            i += 1
-        out.write('</%s>' % element)
-    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
-        out.write(sxpr)
-    else:
-        out.write(str(sxpr))
-
-def elementp(sxpr, elt=None):
-    return (isinstance(sxpr, types.ListType)
-            and len(sxpr)
-            and (None == elt or sxpr[0] == elt))
-
-def name(sxpr):
-    val = None
-    if isinstance(sxpr, types.StringType):
-        val = sxpr
-    elif isinstance(sxpr, types.ListType) and len(sxpr):
-        val = sxpr[0]
-    return val
-
-def attributes(sxpr):
-    val = []
-    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
-        attr = sxpr[1]
-        if elementp(attr, k_attr_open):
-            val = attr[1:]
-    return val
-
-def attribute(sxpr, key, val=None):
-    for x in attributes(sxpr):
-        if x[0] == key:
-            val = x[1]
-            break
-    return val
-
-def children(sxpr, elt=None):
-    val = []
-    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
-        i = 1
-        x = sxpr[i]
-        if elementp(x, k_attr_open):
-            i += 1
-        val = sxpr[i : ]
-    if elt:
-        def iselt(x):
-            return elementp(x, elt)
-        val = filter(iselt, val)
-    return val
-
-def child(sxpr, elt, val=None):
-    for x in children(sxpr):
-        if elementp(x, elt):
-            val = x
-            break
-    return val
-
-def child_at(sxpr, index, val=None):
-    kids = children(sxpr)
-    if len(kids) > index:
-        val = kids[index]
-    return val
-
-def child0(sxpr, val=None):
-    return child_at(sxpr, 0, val)
-
-def child1(sxpr, val=None):
-    return child_at(sxpr, 1, val)
-
-def child2(sxpr, val=None):
-    return child_at(sxpr, 2, val)
-
-def child3(sxpr, val=None):
-    return child_at(sxpr, 3, val)
-
-def child4(sxpr, val=None):
-    return child_at(sxpr, 4, val)
-
-def child_value(sxpr, elt, val=None):
-    kid = child(sxpr, elt)
-    if kid:
-        val = child_at(kid, 0, val)
-    return val
-
-def has_id(sxpr, id):
-    """Test if an s-expression has a given id.
-    """
-    return attribute(sxpr, 'id') == id
-
-def with_id(sxpr, id, val=None):
-    """Find the first s-expression with a given id, at any depth.
-
-    sxpr   s-exp or list
-    id     id
-    val    value if not found (default None)
-
-    return s-exp or val
-    """
-    if isinstance(sxpr, types.ListType):
-        for n in sxpr:
-            if has_id(n, id):
-                val = n
-                break
-            v = with_id(n, id)
-            if v is None: continue
-            val = v
-            break
-    return val
-
-def child_with_id(sxpr, id, val=None):
-    """Find the first child with a given id.
-
-    sxpr   s-exp or list
-    id     id
-    val    value if not found (default None)
-
-    return s-exp or val
-    """
-    if isinstance(sxpr, types.ListType):
-        for n in sxpr:
-            if has_id(n, id):
-                val = n
-                break
-    return val
-
-def elements(sxpr, ctxt=None):
-    """Generate elements (at any depth).
-    Visit elements in pre-order.
-    Values generated are (node, context)
-    The context is None if there is no parent, otherwise
-    (index, parent, context) where index is the node's index w.r.t its parent,
-    and context is the parent's context.
-
-    sxpr   s-exp
-
-    returns generator
-    """
-    yield (sxpr, ctxt)
-    i = 0
-    for n in children(sxpr):
-        if isinstance(n, types.ListType):
-            # Calling elements() recursively does not generate recursively,
-            # it just returns a generator object. So we must iterate over it.
-            for v in elements(n, (i, sxpr, ctxt)):
-                yield v
-        i += 1
-
-def parse(io):
-    """Completely parse all input from 'io'.
-
-    io input file object
-    returns list of values, None if incomplete
-    raises ParseError on parse error
-    """
-    pin = Parser()
-    while 1:
-        buf = io.readline()
-        pin.input(buf)
-        if len(buf) == 0:
-            break
-    if pin.ready():
-        val = pin.get_all()
-    else:
-        val = None
-    return val
-   
-
-if __name__ == '__main__':
-    print ">main"
-    pin = Parser()
-    while 1:
-        buf = sys.stdin.read(1024)
-        #buf = sys.stdin.readline()
-        pin.input(buf)
-        while pin.ready():
-            val = pin.get_val()
-            print
-            print '****** val=', val
-        if len(buf) == 0:
-            break
-
diff --git a/tools/xenmgr/lib/xm/__init__.py b/tools/xenmgr/lib/xm/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/tools/xenmgr/lib/xm/create.py b/tools/xenmgr/lib/xm/create.py
deleted file mode 100644 (file)
index d0bfa08..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Domain creation.
-"""
-import string
-import sys
-
-from xenmgr import sxp
-from xenmgr import PrettyPrint
-from xenmgr.XendClient import server
-
-from xenmgr.xm.opts import *
-
-gopts = Opts(use="""[options]
-
-Create a domain.
-""")
-
-gopts.opt('help', short='h',
-         fn=set_true, default=0,
-         use="Print this help.")
-
-gopts.opt('quiet', short='q',
-         fn=set_true, default=0,
-         use="Quiet.")
-
-gopts.opt('path', val='PATH',
-         fn=set_value, default='.:/etc/xen',
-         use="Search path for default scripts.")
-
-gopts.opt('defaults', short='f', val='FILE',
-         fn=set_value, default='xmdefaults',
-         use="Use the given default script.")
-
-gopts.opt('config', short='F', val='FILE',
-         fn=set_value, default=None,
-         use='Domain configuration to use (SXP).')
-
-gopts.opt('load', short='L', val='FILE',
-          fn=set_value, default=None,
-          use='Domain saved state to load.')
-
-gopts.opt('define', short='D', val='VAR=VAL',
-         fn=set_var, default=None,
-         use="""Set a variable before loading defaults, e.g. '-D vmid=3'
-         to set vmid. May be repeated to set more thanone variable.""")
-
-gopts.opt('dryrun', short='n',
-         fn=set_true, default=0,
-         use="Dry run - print the config but don't create the domain.")
-
-gopts.opt('name', short='N', val='NAME',
-          fn=set_value, default=None,
-          use="Domain name.")
-
-gopts.opt('console', short='c',
-         fn=set_true, default=0,
-         use="Connect to console after domain is created.")
-
-gopts.opt('kernel', short='k', val='FILE',
-         fn=set_value, default=None,
-         use="Path to kernel image.")
-
-gopts.opt('ramdisk', short='r', val='FILE',
-         fn=set_value, default='',
-         use="Path to ramdisk.")
-
-gopts.opt('builder', short='b', val='FUNCTION',
-         fn=set_value, default='linux',
-         use="Function to use to build the domain.")
-
-gopts.opt('memory', short='m', val='MEMORY',
-         fn=set_value, default=128,
-         use="Domain memory in MB.")
-
-gopts.opt('blkif',
-          fn=set_true, default=0,
-          use="Make the domain a block device backend.")
-
-gopts.opt('netif',
-          fn=set_true, default=0,
-          use="Make the domain a network interface backend.")
-
-gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE',
-         fn=append_value, default=[],
-         use="""Add a disk device to a domain. The physical device is DEV, which
-         is exported to the domain as VDEV. The disk is read-only if MODE
-         is 'r', read-write if MODE is 'w'.
-         The option may be repeated to add more than one disk.
-         """)
-
-gopts.opt('pci', val='BUS,DEV,FUNC',
-         fn=append_value, default=[],
-         use="""Add a PCI device to a domain, using given params (in hex).
-         For example '-pci c0,02,1a'.
-         The option may be repeated to add more than one pci device.
-         """)
-
-gopts.opt('ipaddr', short='i', val="IPADDR",
-         fn=append_value, default=[],
-         use="Add an IP address to the domain.")
-
-gopts.opt('vif', val="mac=MAC,bridge=BRIDGE",
-         fn=append_value, default=[],
-         use="""Add a network interface with the given MAC address and bridge.
-         If mac is not specified a random MAC address is used.
-         If bridge is not specified the default bridge is used.
-         This option may be repeated to add more than one vif.
-         Specifying vifs will increase the number of interfaces as needed.
-         """)
-
-gopts.opt('nics', val="NUM",
-         fn=set_int, default=1,
-         use="""Set the number of network interfaces.
-         Use the vif option to define interface parameters, otherwise
-         defaults are used. Specifying vifs will increase the
-         number of interfaces as needed.
-         """)
-
-gopts.opt('root', short='R', val='DEVICE',
-         fn=set_value, default='',
-         use="""Set the root= parameter on the kernel command line.
-         Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
-
-gopts.opt('extra', short='E', val="ARGS",
-         fn=set_value, default='',
-         use="Set extra arguments to append to the kernel command line.")
-
-gopts.opt('ip', short='I', val='IPADDR',
-         fn=set_value, default='',
-         use="Set the kernel IP interface address.")
-
-gopts.opt('gateway', val="IPADDR",
-         fn=set_value, default='',
-         use="Set the kernel IP gateway.")
-
-gopts.opt('netmask', val="MASK",
-         fn=set_value, default = '',
-         use="Set the kernel IP netmask.")
-
-gopts.opt('hostname', val="NAME",
-         fn=set_value, default='',
-         use="Set the kernel IP hostname.")
-
-gopts.opt('interface', val="INTF",
-         fn=set_value, default="eth0",
-         use="Set the kernel IP interface name.")
-
-gopts.opt('dhcp', val="off|dhcp",
-         fn=set_value, default='off',
-         use="Set the kernel dhcp option.")
-
-gopts.opt('nfs_server', val="IPADDR",
-         fn=set_value, default=None,
-         use="Set the address of the NFS server for NFS root.")
-
-gopts.opt('nfs_root', val="PATH",
-         fn=set_value, default=None,
-         use="Set the path of the root NFS directory.")
-
-def strip(pre, s):
-    """Strip prefix 'pre' if present.
-    """
-    if s.startswith(pre):
-        return s[len(pre):]
-    else:
-        return s
-
-def configure_image(config, opts):
-    """Create the image config.
-    """
-    config_image = [ opts.builder ]
-    config_image.append([ 'kernel', os.path.abspath(opts.kernel) ])
-    if opts.ramdisk:
-        config_image.append([ 'ramdisk', os.path.abspath(opts.ramdisk) ])
-    if opts.cmdline_ip:
-        cmdline_ip = strip('ip=', opts.cmdline_ip)
-        config_image.append(['ip', cmdline_ip])
-    if opts.root:
-        cmdline_root = strip('root=', opts.root)
-        config_image.append(['root', cmdline_root])
-    if opts.extra:
-        config_image.append(['args', opts.extra])
-    config.append(['image', config_image ])
-    
-def configure_disks(config_devs, opts):
-    """Create the config for disks (virtual block devices).
-    """
-    for (uname, dev, mode) in opts.disk:
-        config_vbd = ['vbd',
-                      ['uname', uname],
-                      ['dev', dev ],
-                      ['mode', mode ] ]
-        config_devs.append(['device', config_vbd])
-
-def configure_pci(config_devs, opts):
-    """Create the config for pci devices.
-    """
-    for (bus, dev, func) in opts.pci:
-        config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
-        config_devs.append(['device', config_pci])
-
-def configure_vifs(config_devs, opts):
-    """Create the config for virtual network interfaces.
-    """
-    vifs = opts.vif
-    vifs_n = max(opts.nics, len(vifs))
-
-    for idx in range(0, vifs_n):
-        if idx < len(vifs):
-            d = vifs[idx]
-            mac = d.get('mac')
-            bridge = d.get('bridge')
-        else:
-            mac = None
-            bridge = None
-        config_vif = ['vif']
-        if mac:
-            config_vif.append(['mac', mac])
-        if bridge:
-            config_vif.append(['bridge', bridge])
-        config_devs.append(['device', config_vif])
-
-def configure_vfr(config, opts):
-     if not opts.ipaddr: return
-     config_vfr = ['vfr']
-     idx = 0 # No way of saying which IP is for which vif?
-     for ip in opts.ipaddr:
-         config_vfr.append(['vif', ['id', idx], ['ip', ip]])
-     config.append(config_vfr)
-
-
-def make_config(opts):
-    """Create the domain configuration.
-    """
-    
-    config = ['vm',
-              ['name', opts.name ],
-              ['memory', opts.memory ] ]
-    if opts.cpu:
-        config.append(['cpu', opts.cpu])
-    if opts.blkif:
-        config.append(['backend', ['blkif']])
-    if opts.netif:
-        config.append(['backend', ['netif']])
-    
-    configure_image(config, opts)
-    config_devs = []
-    configure_disks(config_devs, opts)
-    configure_pci(config_devs, opts)
-    configure_vifs(config_devs, opts)
-    config += config_devs
-    return config
-
-def preprocess_disk(opts):
-    if not opts.disk: return
-    disk = []
-    for v in opts.disk:
-        d = v.split(',')
-        if len(d) != 3:
-            opts.err('Invalid disk specifier: ' + v)
-        disk.append(d)
-    opts.disk = disk
-
-def preprocess_pci(opts):
-    if not opts.pci: return
-    pci = []
-    for v in opts.pci:
-        d = v.split(',')
-        if len(d) != 3:
-            opts.err('Invalid pci specifier: ' + v)
-        # Components are in hex: add hex specifier.
-        hexd = map(lambda v: '0x'+v, d)
-        pci.append(hexd)
-    opts.pci = pci
-
-def preprocess_vifs(opts):
-    if not opts.vif: return
-    vifs = []
-    for vif in opts.vif:
-        d = {}
-        a = vif.split(',')
-        for b in a:
-            (k, v) = b.strip().split('=')
-            k = k.strip()
-            v = v.strip()
-            if k not in ['mac', 'bridge']:
-                opts.err('Invalid vif specifier: ' + vif)
-            d[k] = v
-        vifs.append(d)
-    opts.vif = vifs
-
-def preprocess_ip(opts):
-    setip = (opts.hostname or opts.netmask
-             or opts.gateway or opts.dhcp or opts.interface)
-    if not setip: return
-    #if not opts
-    ip = (opts.ip
-          + ':'
-          + ':' + opts.gateway
-          + ':' + opts.netmask
-          + ':' + opts.hostname
-          + ':' + opts.interface
-          + ':' + opts.dhcp)
-    opts.cmdline_ip = ip
-
-def preprocess_nfs(opts):
-    if (opts.nfs_root or opts.nfs_server):
-        if (not opts.nfs_root) or (not opts.nfs_server):
-            opts.err('Must set nfs root and nfs server')
-    else:
-        return
-    nfs = 'nfsroot=' + opts.nfs_server + ':' + opts.nfs_root
-    opts.extra = nfs + ' ' + opts.extra
-    
-def preprocess(opts):
-    if not opts.kernel:
-        opts.err("No kernel specified")
-    preprocess_disk(opts)
-    preprocess_pci(opts)
-    preprocess_vifs(opts)
-    preprocess_ip(opts)
-    preprocess_nfs(opts)
-         
-def make_domain(opts, config):
-    """Create, build and start a domain.
-    Returns: [int] the ID of the new domain.
-    """
-    if opts.vals.load:
-        filename = os.path.abspath(opts.vals.load)
-        dominfo = server.xend_domain_restore(filename, config)
-    else:
-        dominfo = server.xend_domain_create(config)
-
-    dom = int(sxp.child_value(dominfo, 'id'))
-    console_info = sxp.child(dominfo, 'console')
-    if console_info:
-        console_port = int(sxp.child_value(console_info, 'port'))
-    else:
-        console_port = None
-    
-    if server.xend_domain_unpause(dom) < 0:
-        server.xend_domain_destroy(dom)
-        opts.err("Failed to start domain %d" % dom)
-    opts.info("Started domain %d, console on port %d"
-              % (dom, console_port))
-    return (dom, console_port)
-
-def main(argv):
-    opts = gopts
-    args = opts.parse(argv)
-    if opts.vals.help:
-        opts.usage()
-        return
-    if opts.vals.config:
-        pass
-    else:
-        opts.load_defaults()
-    preprocess(opts.vals)
-    config = make_config(opts.vals)
-    if opts.vals.dryrun:
-        PrettyPrint.prettyprint(config)
-    else:
-        make_domain(opts, config)
-        
-if __name__ == '__main__':
-    main(sys.argv)
diff --git a/tools/xenmgr/lib/xm/main.py b/tools/xenmgr/lib/xm/main.py
deleted file mode 100644 (file)
index 673cccd..0000000
+++ /dev/null
@@ -1,448 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Grand unified management application for Xen.
-"""
-import os
-import os.path
-import sys
-from getopt import getopt
-
-from xenmgr import PrettyPrint
-from xenmgr import sxp
-from xenmgr.XendClient import server
-from xenmgr.xm import create, shutdown
-
-class Prog:
-    """Base class for sub-programs.
-    """
-
-    """Program group it belongs to"""
-    group = 'all'
-    """Program name."""
-    name = '??'
-    """Short program info."""
-    info = ''
-
-    def __init__(self, xm):
-        self.xm = xm
-
-    def err(self, msg):
-        self.xm.err(msg)
-
-    def help(self, args):
-        self.shortHelp(args)
-
-    def shortHelp(self, args):
-        print "%-14s %s" % (self.name, self.info)
-
-    def main(self, args):
-        """Program main entry point.
-        """
-        pass
-
-
-class ProgUnknown(Prog):
-
-    name = 'unknown'
-    info = ''
-    
-    def help(self, args):
-        self.xm.err("Unknown command: %s\nTry '%s help' for more information."
-                    % (args[0], self.xm.name))
-
-    main = help
-
-class Xm:
-    """Main application.
-    """
-
-    def __init__(self):
-        self.name = 'xm'
-        self.unknown = ProgUnknown(self)
-        self.progs = {}
-
-    def err(self, msg):
-        print >>sys.stderr, "Error:", msg
-        sys.exit(1)
-
-    def main(self, args):
-        """Main entry point. Dispatches to the progs.
-        """
-        self.name = args[0]
-        if len(args) < 2:
-            self.err("Missing command\nTry '%s help' for more information."
-                     % self.name)
-        help = self.helparg(args)
-        p = self.getprog(args[1], self.unknown)
-        if help:
-            p.help(args[1:])
-        else:
-            p.main(args[1:])
-
-    def helparg(self, args):
-        for a in args:
-            if a in ['-h', '--help']:
-                return 1
-        return 0
-
-    def prog(self, pklass):
-        """Add a sub-program.
-
-        pklass  program class (Prog subclass)
-        """
-        p = pklass(self)
-        self.progs[p.name] = p
-        return p
-
-    def getprog(self, name, val=None):
-        """Get a sub-program.
-        """
-        return self.progs.get(name, val)
-
-    def proglist(self):
-        """Get a list of sub-programs, ordered by group.
-        """
-        groups = {}
-        for p in self.progs.values():
-            l = groups.get(p.group, [])
-            l.append(p)
-            groups[p.group] = l
-        kl = groups.keys()
-        kl.sort()
-        pl = []
-        for k in kl:
-            l = groups[k]
-            l.sort()
-            pl += l
-        return pl
-        
-# Create the application object, then add the sub-program classes.
-xm = Xm()
-
-class ProgHelp(Prog):
-
-    name = "help"
-    info = "Print help."
-    
-    def help(self, args):
-        if len(args) == 2:
-            name = args[1]
-            p = self.xm.getprog(name)
-            if p:
-                p.help(args[1:])
-            else:
-                print '%s: Unknown command: %s' % (self.name, name)
-        else:
-            for p in self.xm.proglist():
-                p.shortHelp(args)
-            print "\nTry '%s help CMD' for help on CMD" % self.xm.name
-
-    main = help
-
-xm.prog(ProgHelp)
-
-class ProgCreate(Prog):
-
-    group = 'domain'
-    name = "create"
-    info = """Create a domain."""
-
-    def help(self, args):
-        create.main([args[0], '-h'])
-
-    def main(self, args):
-        create.main(args)
-
-xm.prog(ProgCreate)
-
-class ProgSave(Prog):
-    group = 'domain'
-    name = "save"
-    info = """Save domain state (and config) to file."""
-
-    def help(self, args):
-        print args[0], "DOM FILE"
-        print """\nSave domain with id DOM to FILE."""
-        
-    def main(self, args):
-        if len(args) < 3: self.err("%s: Missing arguments" % args[0])
-        dom = args[1]
-        savefile = os.path.abspath(args[2])
-        server.xend_domain_save(dom, savefile)
-
-xm.prog(ProgSave)
-
-class ProgRestore(Prog):
-    group = 'domain'
-    name = "restore"
-    info = """Create a domain from a saved state."""
-
-    def help(self, args):
-        print args[0], "FILE [CONFIG]"
-        print "\nRestore a domain from FILE using configuration CONFIG."
-    
-    def main(self, help, args):
-        if len(args) < 2: self.err("%s: Missing arguments" % args[0])
-        savefile =  os.path.abspath(args[1])
-        if len(args) >= 3:
-            configfile = os.path.abspath(args[2])
-        else:
-            configfile = None
-        info = server.xend_domain_restore(savefile, configfile)
-        PrettyPrint.prettyprint(info)
-
-xm.prog(ProgRestore)
-
-class ProgList(Prog):
-    group = 'domain'
-    name = "list"
-    info = """List info about domains."""
-
-    short_options = 'l'
-    long_options = ['long']
-
-    def help(self, args):
-        if help:
-            print args[0], '[options] [DOM...]'
-            print """\nGet information about domains.
-            Either all domains or the domains given.
-
-            -l, --long   Get more detailed information.
-            """
-            return
-        
-    def main(self, args):
-        use_long = 0
-        (options, params) = getopt(args[1:],
-                                   self.short_options,
-                                   self.long_options)
-        n = len(params)
-        for (k, v) in options:
-            if k in ['-l', '--long']:
-                use_long = 1
-                
-        if n == 0:
-            doms = map(int, server.xend_domains())
-            doms.sort()
-        else:
-            doms = map(int, params)
-            
-        if use_long:
-            self.long_list(doms)
-        else:
-            self.brief_list(doms)
-
-    def brief_list(self, doms):
-        print 'Dom  Name             Mem(MB)  CPU  State  Time(s)'
-        for dom in doms:
-            info = server.xend_domain(dom)
-            d = {}
-            d['dom'] = int(dom)
-            d['name'] = sxp.child_value(info, 'name', '??')
-            d['mem'] = int(sxp.child_value(info, 'memory', '0'))
-            d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
-            d['state'] = sxp.child_value(info, 'state', '??')
-            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
-            print ("%(dom)-4d %(name)-16s %(mem)7d  %(cpu)3d  %(state)5s  %(cpu_time)7.1f" % d)
-
-    def long_list(self, doms):
-        for dom in doms:
-            info = server.xend_domain(dom)
-            print '\nDomain %d' % dom
-            PrettyPrint.prettyprint(info)
-
-xm.prog(ProgList)
-
-class ProgDestroy(Prog):
-    group = 'domain'
-    name = "destroy"
-    info = """Terminate a domain immediately."""
-
-    def help(self, args):
-        print args[0], 'DOM'
-        print '\nTerminate domain DOM immediately.'
-
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing domain" % args[0])
-        dom = args[1]
-        server.xend_domain_destroy(dom)
-
-xm.prog(ProgDestroy)
-
-class ProgShutdown(Prog):
-    group = 'domain'
-    name = "shutdown"
-    info = """Shutdown a domain."""
-
-    def help(self, args):
-        shutdown.main([args[0], '-h'])
-    
-    def main(self, args):
-        shutdown.main(args)
-
-xm.prog(ProgShutdown)
-
-class ProgPause(Prog):
-    group = 'domain'
-    name = "pause"
-    info = """Pause execution of a domain."""
-
-    def help(self, args):
-        print args[0], 'DOM'
-        print '\nPause execution of domain DOM.'
-
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing domain" % args[0])
-        dom = args[1]
-        server.xend_domain_pause(dom)
-
-xm.prog(ProgPause)
-
-class ProgUnpause(Prog):
-    group = 'domain'
-    name = "unpause"
-    info = """Unpause a paused domain."""
-
-    def help(self, args):
-        print args[0], 'DOM'
-        print '\nUnpause execution of domain DOM.'
-
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing domain" % args[0])
-        dom = args[1]
-        server.xend_domain_unpause(dom)
-
-xm.prog(ProgUnpause)
-
-class ProgPincpu(Prog):
-    group = 'domain'
-    name = "pincpu"
-    info = """Pin a domain to a cpu. """
-
-    def help(self, args):
-        print args[0],'DOM CPU'
-        print '\nPin domain DOM to cpu CPU.'
-
-    def main(self, args):
-        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
-        v = map(int, args[1:3])
-        server.xend_domain_pincpu(*v)
-
-xm.prog(ProgPincpu)
-
-class ProgBvt(Prog):
-    group = 'scheduler'
-    name = "bvt"
-    info = """Set BVT scheduler parameters."""
-    
-    def help(self, args):
-        print args[0], "DOM MCUADV WARP WARPL WARPU"
-        print '\nSet Borrowed Virtual Time scheduler parameters.'
-
-    def main(self, args):
-        if len(args) != 6: self.err("%s: Invalid argument(s)" % args[0])
-        v = map(int, args[1:6])
-        server.xend_domain_cpu_bvt_set(*v)
-
-xm.prog(ProgBvt)
-
-class ProgBvtslice(Prog):
-    group = 'scheduler'
-    name = "bvtslice"
-    info = """Set the BVT scheduler slice."""
-
-    def help(self, args):
-        print args[0], 'SLICE'
-        print '\nSet Borrowed Virtual Time scheduler slice.'
-
-    def main(self, args):
-        if len(args) < 2: self.err('%s: Missing slice' % args[0])
-        server.xend_node_cpu_bvt_slice_set(slice)
-
-xm.prog(ProgBvtslice)
-
-class ProgAtropos(Prog):
-    group = 'scheduler'
-    name= "atropos"
-    info = """Set atropos parameters."""
-
-    def help(self, args):
-        print args[0], "DOM PERIOD SLICE LATENCY XTRATIME"
-        print "\nSet atropos parameters."
-
-    def main(self, args):
-        if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
-        v = map(int, args[1:5])
-        server.xend_domain_cpu_atropos_set(*v)
-
-xm.prog(ProgAtropos)
-
-class ProgRrobin(Prog):
-    group = 'scheduler'
-    name = "rrobin"
-    info = """Set round robin slice."""
-
-    def help(self, args):
-        print args[0], "SLICE"
-        print "\nSet round robin scheduler slice."
-
-    def main(self, args):
-        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
-        rrslice = int(args[1])
-        server.xend_node_rrobin_set(rrslice)
-
-xm.prog(ProgRrobin)
-
-class ProgInfo(Prog):
-    group = 'host'
-    name = "info"
-    info = """Get information about the xen host."""
-
-    def main(self, args):
-        info = server.xend_node()
-        for x in info[1:]:
-            print "%-23s:" % x[0], x[1]
-
-xm.prog(ProgInfo)
-
-class ProgConsoles(Prog):
-    group = 'console'
-    name = "consoles"
-    info = """Get information about domain consoles."""
-
-    def main(self, args):
-        l = server.xend_consoles()
-        print "Dom Port  Id"
-        for x in l:
-            info = server.xend_console(x)
-            d = {}
-            d['dom'] = sxp.child(info, 'dst', ['dst', '?', '?'])[1]
-            d['port'] = sxp.child_value(info, 'port', '?')
-            d['id'] = sxp.child_value(info, 'id', '?')
-            print "%(dom)3s %(port)4s %(id)3s" % d
-
-xm.prog(ProgConsoles)
-
-class ProgConsole(Prog):
-    group = 'console'
-    name = "console"
-    info = """Open a console to a domain."""
-    
-    def help(self, args):
-        print "console DOM"
-        print "\nOpen a console to domain DOM."
-
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing domain" % args[0])
-        dom = args[1]
-        info = server.xend_domain(dom)
-        console = sxp.child(info, "console")
-        if not console:
-            self.err("No console information")
-        port = sxp.child_value(console, "port")
-        from xenctl import console_client
-        console_client.connect("localhost", int(port))
-
-xm.prog(ProgConsole)
-
-def main(args):
-    xm.main(args)
diff --git a/tools/xenmgr/lib/xm/opts.py b/tools/xenmgr/lib/xm/opts.py
deleted file mode 100644 (file)
index 5b95152..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Object-oriented command-line option support.
-"""
-from getopt import getopt
-import os
-import os.path
-import sys
-import types
-
-class Opt:
-    """An individual option.
-    """
-    def __init__(self, opts, name, short=None, long=None,
-                 val=None, fn=None, use=None, default=None):
-        """Create an option.
-
-        opts    parent options object
-        name    name of the field it controls
-        short   short (1-char) command line switch (optional)
-        long    long command-line switch. Defaults to option name.
-        val     string used to print option args in help.
-                If val is not specified the option has no arg.
-        fn      function to call when the option is specified.
-        use     usage (help) string
-        default default value if not specified on command-line
-        """
-        self.opts = opts
-        self.name = name
-        self.short = short
-        if long is None:
-            long = name
-        self.long = long
-        self.val = val
-        self.use = use
-        self.default = default
-        self.optkeys = []
-        if self.short:
-            self.optkeys.append('-' + self.short)
-        if self.long:
-            self.optkeys.append('--' + self.long)
-        self.fn = fn
-        self.specified_opt = None
-        self.specified_val = None
-        self.value = None
-        self.set(default)
-
-    def __repr__(self):
-        return self.name + '=' + str(self.specified_val)
-
-    __str__ = __repr__
-
-    def set(self, value):
-        """Set the option value.
-        """
-        self.opts.setopt(self.name, value)
-
-    def get(self):
-        """Get the option value.
-        """
-        return self.opts.getopt(self.name)
-
-    def append(self, value):
-        """Append a value to the option value.
-        """
-        v = self.get() or []
-        v.append(value)
-        self.set(v)
-
-    def short_opt(self):
-        """Short option spec.
-        """
-        if self.short:
-            if self.val:
-                return self.short + ':'
-            else:
-                return self.short
-        else:
-            return None
-
-    def long_opt(self):
-        """Long option spec.
-        """
-        if self.long:
-            if self.val:
-                return self.long + '='
-            else:
-                return self.long
-        else:
-            return None
-
-    def show(self):
-        sep = ''
-        for x in self.optkeys:
-            print sep, x,
-            sep = ','
-        if self.val:
-            print self.val,
-        print
-        if self.use:
-            print '\t',
-            print self.use
-        if self.val:
-            print '\tDefault', self.default or 'None'
-
-    def specify(self, k, v):
-        """Specify the option. Called when the option is set
-        from the command line.
-
-        k  option switch used
-        v  optional value given (if any)
-        """
-        if k in self.optkeys:
-            if self.val is None and v:
-                self.opts.err("Option '%s' does not take a value" % k)
-            self.specified_opt = k
-            self.specified_val = v
-            if self.fn:
-                self.fn(self, k, v)
-            return 1
-        else:
-            return 0
-
-    def specified(self):
-        """Test whether the option has been specified: set
-        from the command line.
-        """
-        return self.specified_opt
-
-class OptVals:
-    """Class to hold option values.
-    """
-    pass
-
-class Opts:
-    """Container for options.
-    """
-    def __init__(self, use=None):
-        """Options constructor.
-
-        use  usage string
-        """
-        self.use = use
-        # List of options.
-        self.options = []
-        # Options indexed by name.
-        self.options_map = {}
-        # Command-line arguments.
-        self.argv = []
-        # Option values.
-        self.vals = OptVals()
-        self.vals.quiet = 0
-        # Variables for default scripts.
-        self.vars = {}
-
-    def __repr__(self):
-        return '\n'.join(map(str, self.options))
-
-    __str__ = __repr__
-
-    def opt(self, name, **args):
-        """Add an option.
-
-        name    option name
-        **args  keyword params for option constructor
-        """
-        x = Opt(self, name, **args)
-        self.options.append(x)
-        self.options_map[name] = x
-        return x
-
-    def setvar(self, var, val):
-        """Set a default script variable.
-        """
-        self.vars[var] = val
-
-    def getvar(self, var):
-        """Get a default script variable.
-        """
-        return self.vars.get(var)
-
-    def option(self, name):
-        """Get an option (object).
-        """
-        return self.options_map.get(name)
-
-    def setopt(self, name, val):
-        """Set an option value.
-        An option can also be set using 'opts.vals.name = val'.
-        """
-        setattr(self.vals, name, val)
-
-    def getopt(self, name):
-        """Get an option value.
-        An option value can also be got using 'opts.vals.name'.
-        """
-        getattr(self.vals, name)
-
-    def specified(self, name):
-        """Test if an option has been specified.
-        """
-        opt = self.option(name)
-        return opt and opt.specified()
-
-    def err(self, msg):
-        """Print an error to stderr and exit.
-        """
-        print >>sys.stderr, "Error:", msg
-        sys.exit(1)
-
-    def info(self, msg):
-        """Print a message to stdout (unless quiet is set).
-        """
-        if self.vals.quiet: return
-        print msg
-
-    def warn(self, msg):
-        """Print a warning to stdout.
-        """
-        print >>sys.stderr, "Warning:", msg
-
-    def parse(self, argv):
-        """Parse arguments argv using the options.
-
-        return remaining arguments
-        """
-        self.argv = argv
-        (vals, args) = getopt(argv[1:], self.short_opts(), self.long_opts())
-        self.args = args
-        for (k, v) in vals:
-            for opt in self.options:
-                if opt.specify(k, v): break
-            else:
-                print >>sys.stderr, "Error: Unknown option:", k
-                self.usage()
-        return args
-
-    def short_opts(self):
-        """Get short options specifier for getopt.
-        """
-        l = []
-        for x in self.options:
-            y = x.short_opt()
-            if not y: continue
-            l.append(y)
-        return ''.join(l)
-
-    def long_opts(self):
-        """Get long options specifier for getopt.
-        """
-        l = []
-        for x in self.options:
-            y = x.long_opt()
-            if not y: continue
-            l.append(y)
-        return l
-
-    def usage(self):
-        print 'Usage: ', self.argv[0], self.use or 'OPTIONS'
-        for opt in self.options:
-            opt.show()
-
-    def load_defaults(self):
-        """Load a defaults script. Assumes these options set:
-        'path'    search path
-        'default' script name
-        """
-        for x in [ '' ] + self.vals.path.split(':'):
-            if x:
-                p = os.path.join(x, self.vals.defaults)
-            else:
-                p = self.vals.defaults
-            if os.path.exists(p):
-                self.load(p)
-                break
-        else:
-            self.err("Cannot open defaults file %s" % self.vals.defaults)
-
-    def load(self, defaults, help=0):
-        """Load a defaults file. Local variables in the file
-        are used to set options with the same names.
-        Variables are not used to set options that are already specified.
-        """
-        # Create global and lobal dicts for the file.
-        # Initialize locals to the vars.
-        # Use exec to do the standard imports and
-        # define variables we are passing to the script.
-        globals = {}
-        locals = {}
-        locals.update(self.vars)
-        cmd = '\n'.join(["import sys",
-                         "import os",
-                         "import os.path",
-                         "xm_file = '%s'" % defaults,
-                         "xm_help = %d" % help ])
-        exec cmd in globals, locals
-        execfile(defaults, globals, locals)
-        if help: return
-        # Extract the values set by the script and set the corresponding
-        # options, if not set on the command line.
-        vtypes = [ types.StringType,
-                   types.ListType,
-                   types.IntType,
-                   types.FloatType
-                   ]
-        for (k, v) in locals.items():
-            if self.specified(k): continue
-            if not(type(v) in vtypes): continue
-            self.setopt(k, v)
-
-def set_true(opt, k, v):
-    """Set an option true."""
-    opt.set(1)
-
-def set_false(opt, k, v):
-    """Set an option false."""
-    opt.set(0)
-
-def set_value(opt, k, v):
-    """Set an option to a valoue."""
-    opt.set(v)
-
-def set_int(opt, k, v):
-    """Set an option to an integer value."""
-    try:
-        v = int(v)
-    except:
-        opt.opts.err('Invalid value: ' + str(v))
-    opt.set(v)
-
-def append_value(opt, k, v):
-    """Append a value to a list option."""
-    opt.append(v)
-
-def set_var(opt, k, v):
-    """Set a default script variable.
-    """
-    (var, val) = v.strip().split('=')
-    opt.opts.setvar(var.strip(), val.strip())
-
diff --git a/tools/xenmgr/lib/xm/shutdown.py b/tools/xenmgr/lib/xm/shutdown.py
deleted file mode 100644 (file)
index 2c78318..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Domain shutdown.
-"""
-import string
-import sys
-import time
-
-from xenmgr.XendClient import server
-from xenmgr.xm.opts import *
-
-gopts = Opts(use="""[options] [DOM]
-
-Shutdown one or more domains gracefully.""")
-
-gopts.opt('help', short='h',
-         fn=set_true, default=0,
-         use="Print this help.")
-
-gopts.opt('all', short='a',
-         fn=set_true, default=0,
-         use="Shutdown all domains.")
-
-gopts.opt('wait', short='w',
-         fn=set_true, default=0,
-         use='Wait for shutdown to complete.')
-
-gopts.opt('norestart', short='n',
-          fn=set_true, default=0,
-          use='Prevent domain restart.')
-
-def shutdown(opts, doms, wait):
-    def domains():
-        return [ int(a) for a in server.xend_domains() ]
-    if doms == None: doms = domains()
-    if 0 in doms:
-        doms.remove(0)
-    for d in doms:
-        server.xend_domain_shutdown(d)
-    if wait:
-        while doms:
-            alive = domains()
-            dead = []
-            for d in doms:
-                if d in alive: continue
-                dead.append(d)
-            for d in dead:
-                opts.info("Domain %d terminated" % d)
-                doms.remove(d)
-            time.sleep(1)
-        opts.info("All domains terminated")
-
-def main_all(opts, args):
-    shutdown(opts, None, opts.vals.wait)
-
-def main_dom(opts, args):
-    if len(args) < 1: opts.err('Missing domain')
-    dom = args[0]
-    try:
-        domid = int(dom)
-    except:
-        opts.err('Invalid domain: ' + dom)
-    shutdown(opts, [ domid ], opts.vals.wait)
-    
-def main(argv):
-    opts = gopts
-    args = opts.parse(argv)
-    if opts.vals.help:
-        opts.usage()
-        return
-    print 'shutdown.main>', len(args), args
-    if opts.vals.all:
-        main_all(opts, args)
-    else:
-        main_dom(opts, args)
-        
diff --git a/tools/xenmgr/netfix b/tools/xenmgr/netfix
deleted file mode 100644 (file)
index 998a78a..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/python
-#  -*- mode: python; -*-
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-#============================================================================
-# Move the IP address from eth0 onto the Xen bridge (nbe-br).
-# Only works if the bridge control utils (brctl) have been installed.
-#============================================================================
-
-from getopt import getopt
-from xenmgr.XendBridge import *
-
-short_options = 'hvqni:b:c'
-long_options  = ['help', 'verbose', 'quiet',
-                 'interface=', 'bridge=', 'create']
-
-def usage():
-    print """Usage:
-    %s [options]
-
-    Reconfigure routing so that <bridge> has the IP address from
-    <interface>. This lets IP carry on working when <interface>
-    is attached to <bridge> for virtual networking.
-    Uses brctl to add <interface> to <bridge>,
-    so this can be run before any domains have been created.
-    """ % sys.argv[0]
-    print """
-    -i, --interface <interface>    interface, default %(interface)s.
-    -b, --bridge <bridge>          bridge, default %(bridge)s.
-    -c, --create                   create the bridge.
-    -v, --verbose                  Print commands.
-    -q, --quiet                    Don't print commands.
-    -n, --dry-run                  Don't execute commands.
-    -h, --help                     Print this help.
-    """ % defaults
-    sys.exit(1)
-
-
-def main():
-    lopts = set_opts(Opts(defaults))
-    lopts.dryrun = 0
-    (options, args) = getopt(sys.argv[1:], short_options, long_options)
-    if args: usage()
-    for k, v in options:
-        if k in ['-h', '--help']:
-            usage()
-        elif k in ['-c', '--create']:
-            lopts.create = 1
-        elif k in ['-i', '--interface']:
-            lopts.interface = v
-        elif k in ['-b', '--bridge']:
-            lopts.bridge = v
-        elif k in ['-q', '--quiet']:
-            lopts.verbose = 0
-        elif k in ['-v', '--verbose']:
-            lopts.verbose = 1
-        elif k in ['-n', '--dry-run']:
-            lopts.dryrun = 1
-    reconfigure(lopts.interface, lopts.bridge)
-
-if __name__ == '__main__':
-    main()
diff --git a/tools/xenmgr/setup.py b/tools/xenmgr/setup.py
deleted file mode 100644 (file)
index b7f7613..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-
-from distutils.core import setup, Extension
-
-PACKAGE = 'xenmgr'
-VERSION = '1.0'
-
-setup(name            = PACKAGE,
-      version         = VERSION,
-      description     = 'Xen Management API',
-      author          = 'Mike Wray',
-      author_email    = 'mike.wray@hp.com',
-      packages        = [ PACKAGE, PACKAGE + '.server', PACKAGE + '.xm' ],
-      package_dir     = { PACKAGE: 'lib' },
-      )
diff --git a/tools/xenmgr/xend b/tools/xenmgr/xend
deleted file mode 100644 (file)
index e575eec..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/python
-#  -*- mode: python; -*-
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Xen management daemon. Lives in /usr/sbin.
-   Provides console server and HTTP management api.
-
-   Run:
-
-   xend start
-
-   The daemon is stopped with:
-
-   xend stop
-
-   Unfortunately restarting it upsets the channel to dom0 and
-   domain management stops working - needs a reboot to fix.
-"""
-import os
-import sys
-from xenmgr.server import SrvConsoleServer
-
-def main():
-    daemon = SrvConsoleServer.instance()
-    if not sys.argv[1:]:
-        print 'usage: %s {start|stop|restart}' % sys.argv[0]
-    elif os.fork():
-        pid, status = os.wait()
-        return status >> 8
-    elif sys.argv[1] == 'start':
-        return daemon.start()
-    elif sys.argv[1] == 'stop':
-        return daemon.stop()
-    elif sys.argv[1] == 'restart':
-        return daemon.stop() or daemon.start()
-    else:
-        print 'not an option:', sys.argv[1]
-    return 1
-
-if __name__ == '__main__':
-    sys.exit(main())
diff --git a/tools/xenmgr/xenmgrd b/tools/xenmgr/xenmgrd
deleted file mode 100755 (executable)
index c871d4d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Xen management daemon. Lives in /usr/sbin.
-   Run after running xend to provide http access to the management API.
-
-   NO LONGER NEEDED.
-"""
-from xenmgr.server import SrvServer
-SrvServer.main()
diff --git a/tools/xenmgr/xm b/tools/xenmgr/xm
deleted file mode 100755 (executable)
index ff5bbd7..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/python
-#  -*- mode: python; -*-
-import sys
-from xenmgr.xm import main
-
-main.main(sys.argv)
index 6a03b42499835c24f9d16fbbcb791b747fe23aaf..cce1150b1659659411ca9a73d0a5d50f2214939c 100644 (file)
@@ -3,7 +3,7 @@ CC       = gcc
 CFLAGS   = -Wall -O3 -Werror
 CFLAGS  += -I../../xen/include/hypervisor-ifs
 CFLAGS  += -I../../linux-xen-sparse/include
-CFLAGS  += -I../xend/lib
+CFLAGS  += -I../xu/lib
 
 HDRS     = $(wildcard *.h)
 OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
diff --git a/tools/xu/lib/__init__.py b/tools/xu/lib/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/xu/lib/domain_controller.h b/tools/xu/lib/domain_controller.h
new file mode 100644 (file)
index 0000000..76dd164
--- /dev/null
@@ -0,0 +1,532 @@
+/******************************************************************************
+ * domain_controller.h
+ * 
+ * Interface to server controller (e.g., 'xend'). This header file defines the 
+ * interface that is shared with guest OSes.
+ * 
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __DOMAIN_CONTROLLER_H__
+#define __DOMAIN_CONTROLLER_H__
+
+
+#ifndef BASIC_START_INFO
+#error "Xen header file hypervisor-if.h must already be included here."
+#endif
+
+
+/*
+ * EXTENDED BOOTSTRAP STRUCTURE FOR NEW DOMAINS.
+ */
+
+typedef struct {
+    BASIC_START_INFO;
+    u16 domain_controller_evtchn; /* 320 */
+} PACKED extended_start_info_t; /* 322 bytes */
+#define SIF_BLK_BE_DOMAIN (1<<4)  /* Is this a block backend domain? */
+#define SIF_NET_BE_DOMAIN (1<<5)  /* Is this a net backend domain? */
+
+
+/*
+ * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
+ * interpreted by control software to determine the appropriate action. These 
+ * are only really advisories: the controller can actually do as it likes.
+ */
+#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
+#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
+#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
+
+
+/*
+ * CONTROLLER MESSAGING INTERFACE.
+ */
+
+typedef struct {
+    u8 type;     /*  0: echoed in response */
+    u8 subtype;  /*  1: echoed in response */
+    u8 id;       /*  2: echoed in response */
+    u8 length;   /*  3: number of bytes in 'msg' */
+    u8 msg[60];  /*  4: type-specific message data */
+} PACKED control_msg_t; /* 64 bytes */
+
+#define CONTROL_RING_SIZE 8
+typedef u32 CONTROL_RING_IDX;
+#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
+
+typedef struct {
+    control_msg_t tx_ring[CONTROL_RING_SIZE];   /*    0: guest -> controller */
+    control_msg_t rx_ring[CONTROL_RING_SIZE];   /*  512: controller -> guest */
+    CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
+    CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
+} PACKED control_if_t; /* 1040 bytes */
+
+/*
+ * Top-level command types.
+ */
+#define CMSG_CONSOLE        0  /* Console                 */
+#define CMSG_BLKIF_BE       1  /* Block-device backend    */
+#define CMSG_BLKIF_FE       2  /* Block-device frontend   */
+#define CMSG_NETIF_BE       3  /* Network-device backend  */
+#define CMSG_NETIF_FE       4  /* Network-device frontend */
+#define CMSG_SHUTDOWN       6  /* Shutdown messages       */
+
+
+/******************************************************************************
+ * CONSOLE DEFINITIONS
+ */
+
+/*
+ * Subtypes for console messages.
+ */
+#define CMSG_CONSOLE_DATA       0
+
+
+/******************************************************************************
+ * BLOCK-INTERFACE FRONTEND DEFINITIONS
+ */
+
+/* Messages from domain controller to guest. */
+#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED   0
+
+/* Messages from guest to domain controller. */
+#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
+#define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
+#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
+
+/* These are used by both front-end and back-end drivers. */
+#define blkif_vdev_t   u16
+#define blkif_pdev_t   u16
+#define blkif_sector_t u64
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
+ *  Notify a guest about a status change on one of its block interfaces.
+ *  If the interface is DESTROYED or DOWN then the interface is disconnected:
+ *   1. The shared-memory frame is available for reuse.
+ *   2. Any unacknowledged messgaes pending on the interface were dropped.
+ */
+#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
+#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
+#define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
+typedef struct {
+    u32 handle; /*  0 */
+    u32 status; /*  4 */
+    u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
+} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
+
+/*
+ * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the front-end driver is DOWN or UP.
+ *  When the driver goes DOWN then the controller will send no more
+ *  status-change notifications. When the driver comes UP then the controller
+ *  will send a notification for each interface that currently exists.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically take the interfaces DOWN.
+ */
+#define BLKIF_DRIVER_STATUS_DOWN   0
+#define BLKIF_DRIVER_STATUS_UP     1
+typedef struct {
+    /* IN */
+    u32 status;        /*  0: BLKIF_DRIVER_STATUS_??? */
+    /* OUT */
+    /*
+     * Tells driver how many interfaces it should expect to immediately
+     * receive notifications about.
+     */
+    u32 nr_interfaces; /*  4 */
+} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_CONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_CONNECTED message.
+ */
+typedef struct {
+    u32      handle;      /*  0 */
+    u32      __pad;
+    memory_t shmem_frame; /*  8 */
+    MEMORY_PADDING;
+} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_DISCONNECTED message.
+ */
+typedef struct {
+    u32 handle; /*  0 */
+} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * BLOCK-INTERFACE BACKEND DEFINITIONS
+ */
+
+/* Messages from domain controller. */
+#define CMSG_BLKIF_BE_CREATE      0  /* Create a new block-device interface. */
+#define CMSG_BLKIF_BE_DESTROY     1  /* Destroy a block-device interface.    */
+#define CMSG_BLKIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
+#define CMSG_BLKIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
+#define CMSG_BLKIF_BE_VBD_CREATE  4  /* Create a new VBD for an interface.   */
+#define CMSG_BLKIF_BE_VBD_DESTROY 5  /* Delete a VBD from an interface.      */
+#define CMSG_BLKIF_BE_VBD_GROW    6  /* Append an extent to a given VBD.     */
+#define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
+
+/* Messages to domain controller. */
+#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
+
+/*
+ * Message request/response definitions for block-device messages.
+ */
+
+typedef struct {
+    blkif_sector_t sector_start;   /*  0 */
+    blkif_sector_t sector_length;  /*  8 */
+    blkif_pdev_t   device;         /* 16 */
+    u16            __pad;          /* 18 */
+} PACKED blkif_extent_t; /* 20 bytes */
+
+/* Non-specific 'okay' return. */
+#define BLKIF_BE_STATUS_OKAY                0
+/* Non-specific 'error' return. */
+#define BLKIF_BE_STATUS_ERROR               1
+/* The following are specific error returns. */
+#define BLKIF_BE_STATUS_INTERFACE_EXISTS    2
+#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
+#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
+#define BLKIF_BE_STATUS_VBD_EXISTS          5
+#define BLKIF_BE_STATUS_VBD_NOT_FOUND       6
+#define BLKIF_BE_STATUS_OUT_OF_MEMORY       7
+#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    8
+#define BLKIF_BE_STATUS_MAPPING_ERROR       9
+
+/* This macro can be used to create an array of descriptive error strings. */
+#define BLKIF_BE_STATUS_ERRORS {    \
+    "Okay",                         \
+    "Non-specific error",           \
+    "Interface already exists",     \
+    "Interface not found",          \
+    "Interface is still connected", \
+    "VBD already exists",           \
+    "VBD not found",                \
+    "Out of memory",                \
+    "Extent not found for VBD",     \
+    "Could not map domain memory" }
+
+/*
+ * CMSG_BLKIF_BE_CREATE:
+ *  When the driver sends a successful response then the interface is fully
+ *  created. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_create_t; /* 12 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DESTROY:
+ *  When the driver sends a successful response then the interface is fully
+ *  torn down. The controller will send a DESTROYED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify interface to be destroyed. */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_destroy_t; /* 12 bytes */
+
+/*
+ * CMSG_BLKIF_BE_CONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  connected. The controller will send a CONNECTED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    memory_t   shmem_frame;   /*  8: Page cont. shared comms window.     */
+    MEMORY_PADDING;
+    u32        evtchn;        /* 16: Event channel for notifications.    */
+    /* OUT */
+    u32        status;        /* 20 */
+} PACKED blkif_be_connect_t;  /* 24 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DISCONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  disconnected. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_disconnect_t; /* 12 bytes */
+
+/* CMSG_BLKIF_BE_VBD_CREATE */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id for this VBD. */
+    u16        readonly;      /* 10: Non-zero -> VBD isn't writeable.    */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_create_t; /* 16 bytes */
+
+/* CMSG_BLKIF_BE_VBD_DESTROY */
+typedef struct {
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 10 */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
+
+/* CMSG_BLKIF_BE_VBD_GROW */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_extent_t extent;    /*  8: Physical extent to append to VBD.   */
+    blkif_vdev_t vdevice;     /* 28: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 30 */
+    /* OUT */
+    u32        status;        /* 32 */
+} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
+
+/* CMSG_BLKIF_BE_VBD_SHRINK */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 10 */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the back-end driver is DOWN or UP.
+ *  If the driver goes DOWN while interfaces are still UP, the controller
+ *  will automatically send DOWN notifications.
+ */
+typedef struct {
+    u32        status;        /*  0: BLKIF_DRIVER_STATUS_??? */
+} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * NETWORK-INTERFACE FRONTEND DEFINITIONS
+ */
+
+/* Messages from domain controller to guest. */
+#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
+
+/* Messages from guest to domain controller. */
+#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
+#define CMSG_NETIF_FE_INTERFACE_CONNECT         33
+#define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
+ *  Notify a guest about a status change on one of its network interfaces.
+ *  If the interface is DESTROYED or DOWN then the interface is disconnected:
+ *   1. The shared-memory frame is available for reuse.
+ *   2. Any unacknowledged messgaes pending on the interface were dropped.
+ */
+#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
+#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
+#define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
+typedef struct {
+    u32        handle; /*  0 */
+    u32        status; /*  4 */
+    u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
+    u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
+} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
+
+/*
+ * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the front-end driver is DOWN or UP.
+ *  When the driver goes DOWN then the controller will send no more
+ *  status-change notifications. When the driver comes UP then the controller
+ *  will send a notification for each interface that currently exists.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically take the interfaces DOWN.
+ */
+#define NETIF_DRIVER_STATUS_DOWN   0
+#define NETIF_DRIVER_STATUS_UP     1
+typedef struct {
+    /* IN */
+    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
+    /* OUT */
+    /*
+     * Tells driver how many interfaces it should expect to immediately
+     * receive notifications about.
+     */
+    u32        nr_interfaces; /*  4 */
+} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_CONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_CONNECTED message.
+ */
+typedef struct {
+    u32        handle;         /*  0 */
+    u32        __pad;          /*  4 */
+    memory_t   tx_shmem_frame; /*  8 */
+    MEMORY_PADDING;
+    memory_t   rx_shmem_frame; /* 16 */
+    MEMORY_PADDING;
+} PACKED netif_fe_interface_connect_t; /* 24 bytes */
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_DISCONNECTED message.
+ */
+typedef struct {
+    u32        handle;        /*  0 */
+} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * NETWORK-INTERFACE BACKEND DEFINITIONS
+ */
+
+/* Messages from domain controller. */
+#define CMSG_NETIF_BE_CREATE      0  /* Create a new net-device interface. */
+#define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
+#define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
+#define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
+
+/* Messages to domain controller. */
+#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
+
+/*
+ * Message request/response definitions for net-device messages.
+ */
+
+/* Non-specific 'okay' return. */
+#define NETIF_BE_STATUS_OKAY                0
+/* Non-specific 'error' return. */
+#define NETIF_BE_STATUS_ERROR               1
+/* The following are specific error returns. */
+#define NETIF_BE_STATUS_INTERFACE_EXISTS    2
+#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
+#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
+#define NETIF_BE_STATUS_OUT_OF_MEMORY       5
+#define NETIF_BE_STATUS_MAPPING_ERROR       6
+
+/* This macro can be used to create an array of descriptive error strings. */
+#define NETIF_BE_STATUS_ERRORS {    \
+    "Okay",                         \
+    "Non-specific error",           \
+    "Interface already exists",     \
+    "Interface not found",          \
+    "Interface is still connected", \
+    "Out of memory",                \
+    "Could not map domain memory" }
+
+/*
+ * CMSG_NETIF_BE_CREATE:
+ *  When the driver sends a successful response then the interface is fully
+ *  created. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
+    u8         mac[6];        /*  8 */
+    u16        __pad;         /* 14 */
+    /* OUT */
+    u32        status;        /* 16 */
+} PACKED netif_be_create_t; /* 20 bytes */
+
+/*
+ * CMSG_NETIF_BE_DESTROY:
+ *  When the driver sends a successful response then the interface is fully
+ *  torn down. The controller will send a DESTROYED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify interface to be destroyed. */
+    u32        netif_handle;  /*  4: ...ditto...                         */
+    /* OUT */
+    u32   status;             /*  8 */
+} PACKED netif_be_destroy_t; /* 12 bytes */
+
+/*
+ * CMSG_NETIF_BE_CONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  connected. The controller will send a CONNECTED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;          /*  0: Domain attached to new interface.   */
+    u32        netif_handle;   /*  4: Domain-specific interface handle.   */
+    memory_t   tx_shmem_frame; /*  8: Page cont. tx shared comms window.  */
+    MEMORY_PADDING;
+    memory_t   rx_shmem_frame; /* 16: Page cont. rx shared comms window.  */
+    MEMORY_PADDING;
+    u16        evtchn;         /* 24: Event channel for notifications.    */
+    u16        __pad;          /* 26 */
+    /* OUT */
+    u32        status;         /* 28 */
+} PACKED netif_be_connect_t; /* 32 bytes */
+
+/*
+ * CMSG_NETIF_BE_DISCONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  disconnected. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED netif_be_disconnect_t; /* 12 bytes */
+
+/*
+ * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the back-end driver is DOWN or UP.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically send DOWN notifications.
+ */
+typedef struct {
+    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
+} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * SHUTDOWN DEFINITIONS
+ */
+
+/*
+ * Subtypes for shutdown messages.
+ */
+#define CMSG_SHUTDOWN_POWEROFF  0   /* Clean shutdown (SHUTDOWN_poweroff).   */
+#define CMSG_SHUTDOWN_REBOOT    1   /* Clean shutdown (SHUTDOWN_reboot).     */
+#define CMSG_SHUTDOWN_SUSPEND   2   /* Create suspend info, then             */
+                                    /* SHUTDOWN_suspend.                     */
+
+#endif /* __DOMAIN_CONTROLLER_H__ */
diff --git a/tools/xu/lib/xu.c b/tools/xu/lib/xu.c
new file mode 100644 (file)
index 0000000..48c9759
--- /dev/null
@@ -0,0 +1,1386 @@
+/******************************************************************************
+ * utils.c
+ * 
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#include <Python.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <xc.h>
+
+#include <hypervisor-if.h>
+#include "domain_controller.h"
+
+#include <asm-xen/proc_cmd.h>
+
+#define XENPKG "xen.ext.xu"
+
+/* Needed for Python versions earlier than 2.3. */
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC DL_EXPORT(void)
+#endif
+
+/* NB. The following should be kept in sync with the kernel's evtchn driver. */
+#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
+#define EVTCHN_DEV_MAJOR 10
+#define EVTCHN_DEV_MINOR 200
+#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
+#define PORT_EXCEPTION  0x8000   /* An exceptional notification.        */
+#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
+/* /dev/xen/evtchn ioctls: */
+/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
+#define EVTCHN_RESET  _IO('E', 1)
+/* EVTCHN_BIND: Bind to teh specified event-channel port. */
+#define EVTCHN_BIND   _IO('E', 2)
+/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
+#define EVTCHN_UNBIND _IO('E', 3)
+
+/* Size of a machine page frame. */
+#define PAGE_SIZE 4096
+
+
+/*
+ * *********************** NOTIFIER ***********************
+ */
+
+typedef struct {
+    PyObject_HEAD;
+    int evtchn_fd;
+} xu_notifier_object;
+
+static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    u16 v;
+    int bytes;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+    
+    while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
+    {
+        if ( errno == EINTR )
+            continue;
+        if ( errno == EAGAIN )
+            goto none;
+        return PyErr_SetFromErrno(PyExc_IOError);
+    }
+    
+    if ( bytes == sizeof(v) )
+        return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK);
+
+ none:
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    u16 v;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    v = (u16)idx;
+    
+    (void)write(xun->evtchn_fd, &v, sizeof(v));
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
+        return PyErr_SetFromErrno(PyExc_IOError);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
+        return PyErr_SetFromErrno(PyExc_IOError);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    return PyInt_FromLong(xun->evtchn_fd);
+}
+
+static PyMethodDef xu_notifier_methods[] = {
+    { "read",
+      (PyCFunction)xu_notifier_read,
+      METH_VARARGS,
+      "Read a (@port, @type) pair.\n" },
+
+    { "unmask", 
+      (PyCFunction)xu_notifier_unmask,
+      METH_VARARGS,
+      "Unmask notifications for a @port.\n" },
+
+    { "bind", 
+      (PyCFunction)xu_notifier_bind,
+      METH_VARARGS,
+      "Get notifications for a @port.\n" },
+
+    { "unbind", 
+      (PyCFunction)xu_notifier_unbind,
+      METH_VARARGS,
+      "No longer get notifications for a @port.\n" },
+
+    { "fileno", 
+      (PyCFunction)xu_notifier_fileno,
+      METH_VARARGS,
+      "Return the file descriptor for the notification channel.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_notifier_type;
+
+static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
+
+ reopen:
+    xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
+    if ( xun->evtchn_fd == -1 )
+    {
+        if ( (errno == ENOENT) &&
+             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
+             (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, 
+                    (EVTCHN_DEV_MAJOR << 8) | EVTCHN_DEV_MINOR) == 0) )
+            goto reopen;
+        PyObject_Del((PyObject *)xun);
+        return PyErr_SetFromErrno(PyExc_IOError);
+    }
+
+    return (PyObject *)xun;
+}
+
+static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
+{
+    if ( strcmp(name, "EXCEPTION") == 0 )
+        return PyInt_FromLong(PORT_EXCEPTION);
+    if ( strcmp(name, "NORMAL") == 0 )
+        return PyInt_FromLong(PORT_NORMAL);
+    return Py_FindMethod(xu_notifier_methods, obj, name);
+}
+
+static void xu_notifier_dealloc(PyObject *self)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    (void)close(xun->evtchn_fd);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_notifier_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "notifier",
+    sizeof(xu_notifier_object),
+    0,
+    xu_notifier_dealloc, /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_notifier_getattr, /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** MESSAGE ***********************
+ */
+
+#define TYPE(_x,_y) (((_x)<<8)|(_y))
+#define P2C(_struct, _field, _ctype)                                      \
+    do {                                                                  \
+        PyObject *obj;                                                    \
+        if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL )     \
+        {                                                                 \
+            if ( PyInt_Check(obj) )                                       \
+            {                                                             \
+                ((_struct *)&xum->msg.msg[0])->_field =                   \
+                  (_ctype)PyInt_AsLong(obj);                              \
+                dict_items_parsed++;                                      \
+            }                                                             \
+            else if ( PyLong_Check(obj) )                                 \
+            {                                                             \
+                ((_struct *)&xum->msg.msg[0])->_field =                   \
+                  (_ctype)PyLong_AsUnsignedLongLong(obj);                 \
+                dict_items_parsed++;                                      \
+            }                                                             \
+        }                                                                 \
+        xum->msg.length = sizeof(_struct);                                \
+    } while ( 0 )
+#define C2P(_struct, _field, _pytype, _ctype)                             \
+    do {                                                                  \
+        PyObject *obj = Py ## _pytype ## _From ## _ctype                  \
+                        (((_struct *)&xum->msg.msg[0])->_field);          \
+        if ( dict == NULL ) dict = PyDict_New();                          \
+        PyDict_SetItemString(dict, #_field, obj);                         \
+    } while ( 0 )
+
+typedef struct {
+    PyObject_HEAD;
+    control_msg_t msg;
+} xu_message_object;
+
+static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    char *str;
+    int len;
+
+    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+        return NULL;
+
+    if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
+    {
+        PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
+        return NULL;
+    }
+
+    memcpy(&xum->msg.msg[xum->msg.length], str, len);
+    xum->msg.length += len;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    PyObject *payload;
+    int dict_items_parsed = 0;
+
+    if ( !PyArg_ParseTuple(args, "O", &payload) )
+        return NULL;
+
+    if ( !PyDict_Check(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
+        return NULL;
+    }
+
+    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    }
+
+    if ( dict_items_parsed != PyDict_Size(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
+        return NULL;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    PyObject *dict = NULL;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
+        C2P(blkif_fe_interface_status_changed_t, handle, Int, Long);
+        C2P(blkif_fe_interface_status_changed_t, status, Int, Long);
+        C2P(blkif_fe_interface_status_changed_t, evtchn, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
+        C2P(blkif_fe_driver_status_changed_t, status, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
+        C2P(blkif_fe_interface_connect_t, handle,      Int, Long);
+        C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
+        C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
+        C2P(blkif_be_create_t, domid,        Int, Long);
+        C2P(blkif_be_create_t, blkif_handle, Int, Long);
+        C2P(blkif_be_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
+        C2P(blkif_be_destroy_t, domid,        Int, Long);
+        C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
+        C2P(blkif_be_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
+        C2P(blkif_be_connect_t, domid,        Int, Long);
+        C2P(blkif_be_connect_t, blkif_handle, Int, Long);
+        C2P(blkif_be_connect_t, shmem_frame,  Int, Long);
+        C2P(blkif_be_connect_t, evtchn,       Int, Long);
+        C2P(blkif_be_connect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
+        C2P(blkif_be_disconnect_t, domid,        Int, Long);
+        C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
+        C2P(blkif_be_disconnect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
+        C2P(blkif_be_vbd_create_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_create_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_create_t, readonly,     Int, Long);
+        C2P(blkif_be_vbd_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
+        C2P(blkif_be_vbd_destroy_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_destroy_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
+        C2P(blkif_be_vbd_grow_t, domid,         Int, Long);
+        C2P(blkif_be_vbd_grow_t, blkif_handle,  Int, Long);
+        C2P(blkif_be_vbd_grow_t, vdevice,       Int, Long);
+        C2P(blkif_be_vbd_grow_t, extent.sector_start, 
+             Long, UnsignedLongLong);
+        C2P(blkif_be_vbd_grow_t, extent.sector_length, 
+             Long, UnsignedLongLong);
+        C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
+        C2P(blkif_be_vbd_grow_t, status,        Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
+        C2P(blkif_be_vbd_shrink_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_shrink_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_shrink_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED):
+        C2P(blkif_be_driver_status_changed_t, status, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
+        C2P(netif_fe_interface_status_changed_t, handle, Int, Long);
+        C2P(netif_fe_interface_status_changed_t, status, Int, Long);
+        C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        C2P(netif_fe_driver_status_changed_t, status,        Int, Long);
+        C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
+        C2P(netif_fe_interface_connect_t, handle,         Int, Long);
+        C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
+        C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
+        C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
+        C2P(netif_be_create_t, domid,        Int, Long);
+        C2P(netif_be_create_t, netif_handle, Int, Long);
+        C2P(netif_be_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
+        C2P(netif_be_destroy_t, domid,        Int, Long);
+        C2P(netif_be_destroy_t, netif_handle, Int, Long);
+        C2P(netif_be_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
+        C2P(netif_be_connect_t, domid,          Int, Long);
+        C2P(netif_be_connect_t, netif_handle,   Int, Long);
+        C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
+        C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
+        C2P(netif_be_connect_t, evtchn,         Int, Long);
+        C2P(netif_be_connect_t, status,         Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
+        C2P(netif_be_disconnect_t, domid,        Int, Long);
+        C2P(netif_be_disconnect_t, netif_handle, Int, Long);
+        C2P(netif_be_disconnect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED):
+        C2P(netif_be_driver_status_changed_t, status, Int, Long);
+        return dict;
+    }
+
+    return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
+}
+
+static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    return Py_BuildValue("{s:i,s:i,s:i}",
+                         "type",    xum->msg.type,
+                         "subtype", xum->msg.subtype,
+                         "id",      xum->msg.id);
+}
+
+static PyMethodDef xu_message_methods[] = {
+    { "append_payload", 
+      (PyCFunction)xu_message_append_payload,
+      METH_VARARGS,
+      "Append @str to the message payload.\n" },
+
+    { "set_response_fields",
+      (PyCFunction)xu_message_set_response_fields,
+      METH_VARARGS,
+      "Fill in the response fields in a message that was passed to us.\n" },
+
+    { "get_payload",
+      (PyCFunction)xu_message_get_payload,
+      METH_VARARGS,
+      "Return the message payload in string form.\n" },
+
+    { "get_header",
+      (PyCFunction)xu_message_get_header,
+      METH_VARARGS,
+      "Returns a dictionary of values for @type, @subtype, and @id.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_message_type;
+
+static PyObject *xu_message_new(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum;
+    int type, subtype, id, dict_items_parsed = 0;
+    PyObject *payload = NULL;
+
+    if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
+        return NULL;
+
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+
+    xum->msg.type    = type;
+    xum->msg.subtype = subtype;
+    xum->msg.id      = id;
+    xum->msg.length  = 0;
+
+    if ( payload == NULL )
+        return (PyObject *)xum;
+
+    if ( !PyDict_Check(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
+        PyObject_Del((PyObject *)xum);
+        return NULL;
+    }
+
+    switch ( TYPE(type, subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
+        P2C(blkif_fe_interface_status_changed_t, handle, u32);
+        P2C(blkif_fe_interface_status_changed_t, status, u32);
+        P2C(blkif_fe_interface_status_changed_t, evtchn, u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
+        P2C(blkif_be_create_t, domid,        u32);
+        P2C(blkif_be_create_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
+        P2C(blkif_be_destroy_t, domid,        u32);
+        P2C(blkif_be_destroy_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
+        P2C(blkif_be_connect_t, domid,        u32);
+        P2C(blkif_be_connect_t, blkif_handle, u32);
+        P2C(blkif_be_connect_t, shmem_frame,  memory_t);
+        P2C(blkif_be_connect_t, evtchn,       u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
+        P2C(blkif_be_disconnect_t, domid,        u32);
+        P2C(blkif_be_disconnect_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
+        P2C(blkif_be_vbd_create_t, domid,        u32);
+        P2C(blkif_be_vbd_create_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_create_t, vdevice,      blkif_vdev_t);
+        P2C(blkif_be_vbd_create_t, readonly,     u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
+        P2C(blkif_be_vbd_destroy_t, domid,        u32);
+        P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_destroy_t, vdevice,      blkif_vdev_t);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
+        P2C(blkif_be_vbd_grow_t, domid,                u32);
+        P2C(blkif_be_vbd_grow_t, blkif_handle,         u32);
+        P2C(blkif_be_vbd_grow_t, vdevice,              blkif_vdev_t);
+        P2C(blkif_be_vbd_grow_t, extent.sector_start,  blkif_sector_t);
+        P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
+        P2C(blkif_be_vbd_grow_t, extent.device,        blkif_pdev_t);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
+        P2C(blkif_be_vbd_shrink_t, domid,        u32);
+        P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_shrink_t, vdevice,      blkif_vdev_t);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
+        P2C(netif_fe_interface_status_changed_t, handle, u32);
+        P2C(netif_fe_interface_status_changed_t, status, u32);
+        P2C(netif_fe_interface_status_changed_t, evtchn, u16);
+        P2C(netif_fe_interface_status_changed_t, mac[0], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[1], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[2], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[3], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[4], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[5], u8);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
+        P2C(netif_be_create_t, domid,        u32);
+        P2C(netif_be_create_t, netif_handle, u32);
+        P2C(netif_be_create_t, mac[0],       u8);
+        P2C(netif_be_create_t, mac[1],       u8);
+        P2C(netif_be_create_t, mac[2],       u8);
+        P2C(netif_be_create_t, mac[3],       u8);
+        P2C(netif_be_create_t, mac[4],       u8);
+        P2C(netif_be_create_t, mac[5],       u8);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
+        P2C(netif_be_destroy_t, domid,        u32);
+        P2C(netif_be_destroy_t, netif_handle, u32);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
+        P2C(netif_be_connect_t, domid,          u32);
+        P2C(netif_be_connect_t, netif_handle,   u32);
+        P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
+        P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
+        P2C(netif_be_connect_t, evtchn,         u16);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
+        P2C(netif_be_disconnect_t, domid,        u32);
+        P2C(netif_be_disconnect_t, netif_handle, u32);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(netif_fe_driver_status_changed_t, status,        u32);
+        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    }
+
+    if ( dict_items_parsed != PyDict_Size(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
+        PyObject_Del((PyObject *)xum);
+        return NULL;
+    }
+
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_message_getattr(PyObject *obj, char *name)
+{
+    xu_message_object *xum;
+    if ( strcmp(name, "MAX_PAYLOAD") == 0 )
+        return PyInt_FromLong(sizeof(xum->msg.msg));
+    return Py_FindMethod(xu_message_methods, obj, name);
+}
+
+static void xu_message_dealloc(PyObject *self)
+{
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_message_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "message",
+    sizeof(xu_message_object),
+    0,
+    xu_message_dealloc,   /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_message_getattr,   /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** PORT ***********************
+ */
+
+static control_if_t *map_control_interface(int fd, unsigned long pfn)
+{
+    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
+                       MAP_SHARED, fd, pfn * PAGE_SIZE);
+    if ( vaddr == MAP_FAILED )
+        return NULL;
+    return (control_if_t *)(vaddr + 2048);
+}
+static void unmap_control_interface(int fd, control_if_t *c)
+{
+    char *vaddr = (char *)c - 2048;
+    (void)munmap(vaddr, PAGE_SIZE);
+}
+
+typedef struct xu_port_object {
+    PyObject_HEAD;
+    int mem_fd;
+    int xc_handle;
+    u32 remote_dom;
+    int local_port, remote_port;
+    control_if_t    *interface;
+    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
+    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
+} xu_port_object;
+
+static PyObject *port_error;
+
+static int xup_connect(xu_port_object *xup, domid_t dom,
+                       int local_port, int remote_port){
+    // From our prespective rx = producer, tx = consumer.
+    int err = 0;
+    printf("%s> dom=%u %d:%d\n", __FUNCTION__, (unsigned int)dom, 
+           local_port, remote_port);
+
+    // Consumer = tx.
+    //xup->interface->tx_resp_prod = 0;
+    //xup->interface->tx_req_prod = 0;
+    xup->tx_resp_prod = xup->interface->tx_resp_prod;
+    xup->tx_req_cons = xup->interface->tx_resp_prod;
+    printf("%s> tx: %u %u : %u %u\n", __FUNCTION__,
+           (unsigned int)xup->interface->tx_resp_prod,
+           (unsigned int)xup->tx_resp_prod,
+           (unsigned int)xup->tx_req_cons,
+           (unsigned int)xup->interface->tx_req_prod);
+
+    // Producer = rx.
+    //xup->interface->rx_req_prod  = 0;
+    //xup->interface->rx_resp_prod = 0;
+    xup->rx_req_prod  = xup->interface->rx_req_prod;
+    xup->rx_resp_cons = xup->interface->rx_resp_prod;
+    printf("%s> rx: %u %u : %u %u\n", __FUNCTION__,
+           (unsigned int)xup->rx_resp_cons,
+           (unsigned int)xup->interface->rx_resp_prod,
+           (unsigned int)xup->interface->rx_req_prod,
+           (unsigned int)xup->rx_req_prod);
+
+    xup->remote_dom   = dom;
+    xup->local_port   = local_port;
+    xup->remote_port  = remote_port;
+
+    printf("%s< err=%d\n", __FUNCTION__, err);
+    return err;
+}
+
+static PyObject *xu_port_notify(PyObject *self, PyObject *args)
+{
+    xu_port_object *xup = (xu_port_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   c = xup->tx_req_cons;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->tx_req_prod) || 
+         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
+    {
+        PyErr_SetString(port_error, "no request to read");
+        return NULL;
+    }
+
+    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+    if ( xum->msg.length > sizeof(xum->msg.msg) )
+        xum->msg.length = sizeof(xum->msg.msg);
+    xup->tx_req_cons++;
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   p = xup->rx_req_prod;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+        return NULL;
+
+    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
+    {
+        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
+        return NULL;        
+    }
+
+    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
+    {
+        PyErr_SetString(port_error, "no space to write request");
+        return NULL;
+    }
+
+    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
+    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
+
+    xup->rx_req_prod = cif->rx_req_prod = p + 1;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   c = xup->rx_resp_cons;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+    {
+        PyErr_SetString(port_error, "no response to read");
+        return NULL;
+    }
+
+    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+    if ( xum->msg.length > sizeof(xum->msg.msg) )
+        xum->msg.length = sizeof(xum->msg.msg);
+    xup->rx_resp_cons++;
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   p = xup->tx_resp_prod;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+        return NULL;
+
+    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
+    {
+        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
+        return NULL;        
+    }
+
+    if ( p == xup->tx_req_cons )
+    {
+        PyErr_SetString(port_error, "no space to write response");
+        return NULL;
+    }
+
+    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
+    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
+
+    xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   c = xup->tx_req_cons;
+    control_if_t      *cif = xup->interface;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->tx_req_prod) || 
+         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   p = xup->rx_req_prod;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   c = xup->rx_resp_cons;
+    control_if_t      *cif = xup->interface;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_response(
+    PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   p = xup->tx_resp_prod;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( p == xup->tx_req_cons )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyMethodDef xu_port_methods[] = {
+    { "notify",
+      (PyCFunction)xu_port_notify,
+      METH_VARARGS,
+      "Send a notification to the remote end.\n" },
+
+    { "read_request",
+      (PyCFunction)xu_port_read_request,
+      METH_VARARGS,
+      "Read a request message from the control interface.\n" },
+
+    { "write_request",
+      (PyCFunction)xu_port_write_request,
+      METH_VARARGS,
+      "Write a request message to the control interface.\n" },
+
+    { "read_response",
+      (PyCFunction)xu_port_read_response,
+      METH_VARARGS,
+      "Read a response message from the control interface.\n" },
+
+    { "write_response",
+      (PyCFunction)xu_port_write_response,
+      METH_VARARGS,
+      "Write a response message to the control interface.\n" },
+
+    { "request_to_read",
+      (PyCFunction)xu_port_request_to_read,
+      METH_VARARGS,
+      "Returns TRUE if there is a request message to read.\n" },
+
+    { "space_to_write_request",
+      (PyCFunction)xu_port_space_to_write_request,
+      METH_VARARGS,
+      "Returns TRUE if there is space to write a request message.\n" },
+
+    { "response_to_read",
+      (PyCFunction)xu_port_response_to_read,
+      METH_VARARGS,
+      "Returns TRUE if there is a response message to read.\n" },
+
+    { "space_to_write_response",
+      (PyCFunction)xu_port_space_to_write_response,
+      METH_VARARGS,
+      "Returns TRUE if there is space to write a response message.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_port_type;
+
+static PyObject *xu_port_new(PyObject *self, PyObject *args)
+{
+    xu_port_object *xup;
+    u32 dom;
+    int port1, port2;
+    xc_dominfo_t info;
+
+    if ( !PyArg_ParseTuple(args, "i", &dom) )
+        return NULL;
+
+    xup = PyObject_New(xu_port_object, &xu_port_type);
+
+    if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 )
+    {
+        PyErr_SetString(port_error, "Could not open '/dev/mem'");
+        goto fail1;
+    }
+
+    /* Set the General-Purpose Subject whose page frame will be mapped. */
+    (void)ioctl(xup->mem_fd, _IO('M', 1), (unsigned long)dom);
+
+    if ( (xup->xc_handle = xc_interface_open()) == -1 )
+    {
+        PyErr_SetString(port_error, "Could not open Xen control interface");
+        goto fail2;
+    }
+
+    if ( dom == 0 )
+    {
+        /*
+         * The control-interface event channel for DOM0 is already set up.
+         * We use an ioctl to discover the port at our end of the channel.
+         */
+        port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
+        port2 = -1; /* We don't need the remote end of the DOM0 link. */
+        if ( port1 < 0 )
+        {
+            PyErr_SetString(port_error, "Could not open channel to DOM0");
+            goto fail3;
+        }
+    }
+    else if ( xc_evtchn_bind_interdomain(xup->xc_handle, 
+                                         DOMID_SELF, dom, 
+                                         &port1, &port2) != 0 )
+    {
+        PyErr_SetString(port_error, "Could not open channel to domain");
+        goto fail3;
+    }
+
+    if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) ||
+         (info.domid != dom) )
+    {
+        PyErr_SetString(port_error, "Failed to obtain domain status");
+        goto fail4;
+    }
+
+    xup->interface = 
+        map_control_interface(xup->mem_fd, info.shared_info_frame);
+    if ( xup->interface == NULL )
+    {
+        PyErr_SetString(port_error, "Failed to map domain control interface");
+        goto fail4;
+    }
+
+    xup_connect(xup, dom, port1, port2);
+    return (PyObject *)xup;
+
+    
+ fail4:
+    (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
+ fail3:
+    (void)xc_interface_close(xup->xc_handle);
+ fail2:
+    (void)close(xup->mem_fd);
+ fail1:
+    PyObject_Del((PyObject *)xup);
+    return NULL;        
+}
+
+static PyObject *xu_port_getattr(PyObject *obj, char *name)
+{
+    xu_port_object *xup = (xu_port_object *)obj;
+    if ( strcmp(name, "local_port") == 0 )
+        return PyInt_FromLong(xup->local_port);
+    if ( strcmp(name, "remote_port") == 0 )
+        return PyInt_FromLong(xup->remote_port);
+    if ( strcmp(name, "remote_dom") == 0 )
+        return PyInt_FromLong(xup->remote_dom);
+    return Py_FindMethod(xu_port_methods, obj, name);
+}
+
+static void xu_port_dealloc(PyObject *self)
+{
+    xu_port_object *xup = (xu_port_object *)self;
+    unmap_control_interface(xup->mem_fd, xup->interface);
+    if ( xup->remote_dom != 0 )
+        (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
+    (void)xc_interface_close(xup->xc_handle);
+    (void)close(xup->mem_fd);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_port_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "port",
+    sizeof(xu_port_object),
+    0,
+    xu_port_dealloc,     /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_port_getattr,     /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** BUFFER ***********************
+ */
+
+#define BUFSZ 65536
+#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
+typedef unsigned int BUF_IDX;
+
+typedef struct {
+    PyObject_HEAD;
+    char        *buf;
+    unsigned int prod, cons;
+} xu_buffer_object;
+
+static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
+{
+    PyObject *str1, *str2;
+    int len1, len2, c = MASK_BUF_IDX(xub->cons);
+
+    len1 = xub->prod - xub->cons;
+    if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
+        len1 = BUFSZ - c;
+    if ( len1 > max )         /* clip to specified maximum */
+        len1 = max;
+    if ( len1 < 0 )           /* sanity */
+        len1 = 0;
+
+    if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
+        return NULL;
+
+    if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
+    {
+        len2 = max - len1;
+        if ( len2 > MASK_BUF_IDX(xub->prod) )
+            len2 = MASK_BUF_IDX(xub->prod);
+        if ( len2 > 0 )
+        {
+            str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
+            if ( str2 == NULL )
+                return NULL;
+            PyString_ConcatAndDel(&str1, str2);
+            if ( str1 == NULL )
+                return NULL;
+        }
+    }
+
+    return str1;
+}
+
+static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    int max = 1024;
+
+    if ( !PyArg_ParseTuple(args, "|i", &max) )
+        return NULL;
+    
+    return __xu_buffer_peek(xub, max);
+}
+
+static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    PyObject *str;
+    int max = 1024;
+
+    if ( !PyArg_ParseTuple(args, "|i", &max) )
+        return NULL;
+
+    if ( (str = __xu_buffer_peek(xub, max)) != NULL )
+        xub->cons += PyString_Size(str);
+
+    return str;
+}
+
+static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    int max, len;
+
+    if ( !PyArg_ParseTuple(args, "i", &max) )
+        return NULL;
+
+    len = xub->prod - xub->cons;
+    if ( len > max )
+        len = max;
+    if ( len < 0 )
+        len = 0;
+
+    xub->cons += len;
+
+    return PyInt_FromLong(len);
+}
+
+static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    char *str;
+    int len, len1, len2;
+
+    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+        return NULL;
+
+    len1 = len;
+    if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+        len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
+    if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
+        len1 = BUFSZ - (xub->prod - xub->cons);
+
+    if ( len1 == 0 )
+        return PyInt_FromLong(0);
+
+    memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
+    xub->prod += len1;
+
+    if ( len1 < len )
+    {
+        len2 = len - len1;
+        if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+            len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
+        if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
+            len2 = BUFSZ - (xub->prod - xub->cons);
+        if ( len2 != 0 )
+        {
+            memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
+            xub->prod += len2;
+            return PyInt_FromLong(len1 + len2);
+        }
+    }
+
+    return PyInt_FromLong(len1);
+}
+
+static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( xub->cons == xub->prod )
+        return PyInt_FromLong(1);
+
+    return PyInt_FromLong(0);
+}
+
+static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (xub->prod - xub->cons) == BUFSZ )
+        return PyInt_FromLong(1);
+
+    return PyInt_FromLong(0);
+}
+
+static PyMethodDef xu_buffer_methods[] = {
+    { "peek", 
+      (PyCFunction)xu_buffer_peek,
+      METH_VARARGS,
+      "Peek up to @max bytes from the buffer. Returns a string.\n" },
+
+    { "read", 
+      (PyCFunction)xu_buffer_read,
+      METH_VARARGS,
+      "Read up to @max bytes from the buffer. Returns a string.\n" },
+
+    { "discard", 
+      (PyCFunction)xu_buffer_discard,
+      METH_VARARGS,
+      "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
+
+    { "write", 
+      (PyCFunction)xu_buffer_write,
+      METH_VARARGS,
+      "Write @string into buffer. Return number of bytes written.\n" },
+
+    { "empty", 
+      (PyCFunction)xu_buffer_empty,
+      METH_VARARGS,
+      "Return TRUE if the buffer is empty.\n" },
+
+    { "full", 
+      (PyCFunction)xu_buffer_full,
+      METH_VARARGS,
+      "Return TRUE if the buffer is full.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_buffer_type;
+
+static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
+
+    if ( (xub->buf = malloc(BUFSZ)) == NULL )
+    {
+        PyObject_Del((PyObject *)xub);
+        return NULL;
+    }
+
+    xub->prod = xub->cons = 0;
+
+    return (PyObject *)xub;
+}
+
+static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
+{
+    return Py_FindMethod(xu_buffer_methods, obj, name);
+}
+
+static void xu_buffer_dealloc(PyObject *self)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    free(xub->buf);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_buffer_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "buffer",
+    sizeof(xu_buffer_object),
+    0,
+    xu_buffer_dealloc,   /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_buffer_getattr,   /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** MODULE WRAPPER ***********************
+ */
+
+static void handle_child_death(int dummy)
+{
+    while ( waitpid(-1, NULL, WNOHANG) > 0 )
+        continue;
+}
+
+static PyObject *xu_autoreap(PyObject *self, PyObject *args)
+{
+    struct sigaction sa;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = handle_child_death;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+    (void)sigaction(SIGCHLD, &sa, NULL);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMethodDef xu_methods[] = {
+    { "notifier", xu_notifier_new, METH_VARARGS, 
+      "Create a new notifier." },
+    { "message", xu_message_new, METH_VARARGS, 
+      "Create a new communications message." },
+    { "port", xu_port_new, METH_VARARGS, 
+      "Create a new communications port." },
+    { "buffer", xu_buffer_new, METH_VARARGS, 
+      "Create a new ring buffer." },
+    { "autoreap", xu_autoreap, METH_VARARGS,
+      "Ensure that zombie children are automatically reaped by the OS." },
+    { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC initxu(void)
+{
+    PyObject *m, *d;
+
+    m = Py_InitModule(XENPKG, xu_methods);
+
+    d = PyModule_GetDict(m);
+    port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
+    PyDict_SetItemString(d, "PortError", port_error);
+}
diff --git a/tools/xu/setup.py b/tools/xu/setup.py
new file mode 100644 (file)
index 0000000..e342c78
--- /dev/null
@@ -0,0 +1,19 @@
+
+from distutils.core import setup, Extension
+
+xu = Extension("xu",
+                  extra_compile_args   = ["-fno-strict-aliasing"],
+                  include_dirs         = ["../xc/lib",
+                                          "../../xen/include/hypervisor-ifs",
+                                          "../../linux-xen-sparse/include"],
+                  library_dirs         = ["../xc/lib"],
+                  libraries            = ["xc"],
+                  sources              = ["lib/xu.c"])
+
+setup(name = "xu",
+      version = "1.0",
+      #packages = ["xend"],
+      #package_dir = { "xend" : "lib" },
+      ext_package = "xen.ext",
+      ext_modules = [ xu ]
+      )